Plugin best practices and examples

Working with a revision control system (RCS)

Working with a revision control system doesn't involve any special actions. If you have a Plugin in your RCS, do a checkout with your revision control client, then add that Plugin to the development page.

Many revision control systems store versioning information in special hidden files or directories. These hidden files (including files starting with a period) are excluded from the build.

Working with an IDE (Eclipse)

You can use the Eclipse integrated development environment to develop Plugins. It is available at http://www.eclipse.org/.

Eclipse setup

To enable compilation of AppMon Plugins in Eclipse, you need to set up the target platform correctly. Open Eclipse preferences, navigate to Plug-in Development > Target Platform and add a new platform entry which points to the plugins directory in your local AppMon Client installation, usually (for Windows) c:\Program Files (x86)\dynatrace\dynaTrace (version)\client\plugins. If you are using the Webstart Client and have no local client installation, ask your Dynatrace administrator to provide you with the file com.dynatrace.diagnostics.sdk.jar which can be found in the plugins directory of the server or collector installation. Place the file in a directory outside of the plugin project and configure the target platform as previously described. Do not place the file in the plugin/lib directory.

Editing an existing plugin from a plugin jar file

  1. Extract the jar file into a directory of your choice.
  2. Import the plugin into the PDE using the Open button.
  3. Open and save the edit dialog box at least once to create the Eclipse project files. This works around known issue to be fixed in a future AppMon release.
  4. Import the project into eclipse as described below.

Editing a plugin that is managed in the AppMon Client PDE

When creating a project that contains source files, the PDE automatically creates project files for Eclipse (3.4 and higher) that enable you to import the project into Eclipse without further configuration.

  1. Create and configure the Plugin to your needs.
  2. Open Eclipse with any workspace, and select File > Import.
  3. In the import dialog box, select Existing Projects into Workspace and navigate to the base folder of your plugin. The currently configured base folder for plugin development shows in the Client Preferences of the AppMon Client. The default folder name for a Plugin is the Plugin name.
  4. Select your project, then select Finish.
Warning

It is recommended that you manage the libraries used by the Plugin only in the PDE. The PDE re-creates the Eclipse project files to update the classpath whenever the Plugin configuration is saved. This means any configuration that was done in Eclipse is lost.

Debugging a plugin

A plugin executed on an AppMon Server or Collector has two options to transfer debug messages: as status messages (for Monitor and Task Plugins) or using a log file (for all plugins).

Status messages

Each lifecycle method has to return a Status object, which has a message property that can be set in the Plugin. This message is shown in the plugin details of the plugin schedule.

Log messages

Each plugin sends log messages either to <dtinstallation>/log/server or to Collector log directories, depending on the execution target of the Plugin. The log file name starts with the ID of the Task, Monitor, or Action..

Examples

For detailed procedures for creating a Plugin, see Developing a User Plugin.

Creating a performance monitor

  1. Create a new Plugin.
  2. Set the type to Monitor.
  3. Configure the Monitor Metric Group: Set the name to My Performance Monitor, the first metric key to MyTimeValue, and the unit to percent
  4. Finish the New Plugin Wizard.
  5. Open the Plugin Java class file in your preferred text editor.

If, for example, you used com.mycompany.myplugin.MyPlugin as the class name in the wizard, you can find the file in PluginPath/src/com/myplugin/.

This example is a simple Plugin for demonstration purposes only. Most try/catch blocks and other checks are omitted to make the code easier to read.

package com.mycompany.myplugin;

import com.dynatrace.diagnostics.pdk.*;
import java.util.*;

public class MyPlugin implements Monitor {
	// constants
	private static final String HOST = "host";
	private static final String METRIC_GROUP = "MyMetricGroup";
	private static final String METRIC_MY_TIME = "MyTimeValue";

        private static final Logger log = Logger.getLogger(MyPlugin.class.getName());

	private String host;

	@Override
	public Status setup(MonitorEnvironment env) throws Exception {
		// this is one of the hosts which is configured for this monitor instance
		host = env.getHost().getAddress();

		// your implementation to create connection to host.

	        return new Status(Status.Code.SUCCESS);
	}

        private Long getMeasurement() {
                // add your implementation here
                return 42;
        }

	@Override
	public Status execute(MonitorEnvironment env) throws Exception {

		// get the measurement
		Long measurement = getMeasurement();
		if (measurement == null) {
                    log.warning("useful information why no measure could be read");
                    return new Status(Status.StatusCode.ErrorInternal, "failed to get monitor measures");
		}

		// get the monitor measures for the processor time metric
		Collection<MonitorMeasure> measures = env.getMonitorMeasures(METRIC_GROUP, METRIC_MY_TIME);
		if (measures == null) {
			return new Status(Status.Code.INTERNAL_ERROR, "failed to get monitor measures");
		}

		// set the measurement
		for (MonitorMeasure measure : measures) {
			measure.setValue(measurement * 0.001); // the value is scaled by 1000
		}

		return new Status(Status.StatusCode.Success);
	}

	@Override
	public void teardown(MonitorEnvironment env) throws Exception {

            // disconnect from your host

	}
}

Creating an action plugin

  1. Create a new Plugin.
  2. Set the type to Action.
  3. Configure the Plugin properties: Create one property with the key property1 and type string.
  4. Finish the New Plugin Wizard.
  5. Open the Plugin Java class file in your preferred text editor. If, for example you used com.mycompany.myplugin.MyAction as the class name in the wizard, you can find the file in PluginPath/src/com/myplugin/.
package com.mycompany.myplugin;

import java.util.Collection;
import java.util.logging.Logger;
import com.dynatrace.diagnostics.pdk.*;

public class MyAction implements Action {
	private static final Logger log = Logger.getLogger(MyAction.class.getName());

	private static final String ENV_CONFIG_STRING_PROP1 = "property1";

	@Override
	public Status setup(ActionEnvironment env) throws Exception {
		try {
			//setup code
		} catch (Exception e)  {
			return new Status(Status.StatusCode.ErrorInfrastructure, "Setup error.");
		}
		return new Status(Status.StatusCode.Success);
	}

	@Override
	public void teardown(ActionEnvironment env) throws Exception {
		//shutdown code if necessary
	}

	@Override
	public Status execute(ActionEnvironment env) throws Exception {
		String prop1 = env.getConfigString(ENV_CONFIG_STRING_PROP1); //access to configuration properties if necessary

		Collection<Incident> incidents = env.getIncidents();
		for (Incident incident : incidents) {
			String message = incident.getMessage();
			log.info("Incident " + message + " triggered.");
			for (Violation violation : incident.getViolations()) {
				log.info("Measure " + violation.getViolatedMeasure().getName() + " violoated threshold.");
			}
		}
	return new Status(Status.StatusCode.Success);
	}
}

Dynamic monitor measures

This snippet extends the preceding example by creating two dynamic sub-measures for any measures subscribed for the metric mymetric.

... (other execute() code omitted)

Collection<MonitorMeasure> monitorMeasures = env.getMonitorMeasures("mymetricgroup", "mymetric");
for (MonitorMeasure subscribedMonitorMeasure : monitorMeasures) {

     //this books to the "classic" monitor measure
     //this is optional and only to show how it used to be.
     subscribedMonitorMeasure.setValue(42);

     //for this subscribed measure, create a dynamic measure
     MonitorMeasure dynamicMeasure = env.createDynamicMeasure(subscribedMonitorMeasure, "Queue Name", "Queue 1");
     dynamicMeasure.setValue(24);

     //now create another one for a different queue name
     dynamicMeasure = env.createDynamicMeasure(subscribedMonitorMeasure, "Queue Name", "Queue 2");
     dynamicMeasure.setValue(32);

}
...