OneAgent and ActiveGate version 1.299 are the last versions supporting OneAgent and ActiveGate Extensions 1.0 framework. You can continue using Extensions 1.0 if you stay at OneAgent or ActiveGate version 1.299. Note that this means you'll be using an unsupported Python version 3.8. We strongly recommend migrating your extensions to the latest Extensions 2.0 framework.
For more information, see General guidance and how to migrate.
Let’s learn by example. In this tutorial, we’ll walk you through the creation of a basic ActiveGate extension. Your ActiveGate extension will be executed on an ActiveGate and will enable monitoring of the demo application bundled with the ActiveGate Extension SDK.
Dynatrace version 1.176 or newer
Environment ActiveGate. To run extensions with ActiveGate installed on Amazon Linux 2022, you need to install the libxcrypt-compat
library.
Monitoring admin access
Sign in to Dynatrace.
Go to Settings > Monitoring > Monitored technologies and select Add new technology monitoring > Add ActiveGate extension > Download Extension SDK.
Extract the archive to a convenient directory. It contains docs, examples, and the Extension SDK whl
file you'll use to install the SDK.
You'll find example extensions in the examples
directory. In this article, we'll use the CustomCloudTechnology
extension located in the demo_activegate_plugin_multi
directory.
We recommend that you install the Extension SDK using Python Virtual Environment. For guidance, see Virtual Environments and Packages in Python documentation.
whl
file in it and run the following command:pip3 install plugin_sdk-[sdk version number]-py3-none-any.whl
pip3 install plugin_sdk-1.156.0.20181003.61122-py3-none-any.whl
plugin_sdk --help
to verify the Extension SDK installation. For more information, see [Install Extension SDK]plugin-sdk-overview).build_plugin
command takes care of both the Server and ActiveGate. If you installed your Extension SDK on a separate host, which is a more common case, upload your extension to the ActiveGate manually. During the development stage, we recommend you install Extension SDK on the ActiveGate to make your development process easier.build_plugin
command builds the extension package and uploads it to a selected deployment directory. You'll need the Dynatrace Server URL and token to run the command. If you installed the Extension SDK on the ActiveGate host, the SDK will automatically retrieve the server URL from the ActiveGate configuration. Get the token from Settings > Monitoring > Monitored technologies > Custom extensions and save it as the plugin_upload.token
file in the ActiveGate plugin module config directory. By default, %PROGRAMFILES%\dynatrace\remotepluginmodule\agent\conf
on Windows and /opt/dynatrace/remotepluginmodule/agent/conf
on Linux.version
property in the metadata section of your JSON definition.Navigate to the extension SDK \examples\demo_activegate_plugin
directory and run the plugin_sdk build_plugin
command. It will build the extension package from the current directory. When completed, copy the extension package to the ActiveGate deployment directory (%PROGRAMFILES%\dynatrace\remotepluginmodule\plugin_deployment
or /opt/dynatrace/remotepluginmodule/plugin_deployment
and upload the extension to the Dynatrace server your ActiveGate is assigned to. A message similar to this means everything went well.
Copying plugin to target_directory: {plugin_deployment_dir}\custom.remote.python.example_multiCreating plugin archive========================================Plugin deployed successfully into {plugin_deployment_dir}\custom.remote.python.example_multiPlugin archive available at {plugin_deployment_dir}\custom.remote.python.example_multi.zip========================================interactive upload -> oneagent_upload_plugin -p {plugin_deployment_dir}\custom.remote.python.example_multi.zip -s https://{dynatrace_server_URL}:443/api/v1/remoteplugins -t #####################Attempting to send plugin to server https://{dynatrace_server_URL}:443/api/v1/remotepluginsplugin has been uploaded successfully
Congratulations, you have successfully deployed your first ActiveGate extension.
Your first ActiveGate extension will monitor the demo app bundled with the SDK. The demo app simulates the EXAMPLE_SERVICE
technology that runs on a cluster (device group) with two nodes (devices). The demo app API provides access to metrics. Your extension will import the topology and fetch the metrics.
python -m plugin_sdk.demo_app
http://127.0.0.1:8769/
and check the app response.Go to Settings > Monitoring > Monitored technologies > Custom extensions tab.
Open CustomCloudTechnology
extension and configure it.
Verify successful extension start. The Demo Plugin should display the Ok status.
Wait patiently. It takes up to 2 minutes for the first data to be collected.
Go to Technologies & Processes or Technologies & Processes Classic (latest Dynatrace) and find EXAMPLE_SERVICE
tile.
The Group page lets you analyze the group and compare the performance of its members.
Analyze various chart types on device page
Navigate to further details to find memory tab
The ActiveGate extension consists of two key files, Python and JSON. The JSON file defines the presentation of your data on various Dynatrace pages. With the Python file, you can define additional events and create custom properties. See ActiveGate extensions reference and ActiveGate extensions capabilities. Try to play with the files and see how the data presentation is affected.
The extension JSON file consists of the following four main elements:
The metadata contains a list of properties used to identify your extension.
{"name": "custom.remote.python.example_multi","version": "1.18","productiveMinVersion": "1.000","requiredAgentVersion": "1.000","type": "python","entity": "CUSTOM_DEVICE","metricGroup": "tech.Example_Service","technologies": ["EXAMPLE_SERVICE"],"source": {"package": "demo_activegate_plugin_multi","className": "RemoteExamplePlugin","install_requires": ["requests>=2.6.0"]}}
ActiveGate extension name should follow ^ custom.remote.python (\.[a-zA-Z0-9_]+)+$
regex. For example, custom.remote.python.demo
. The name of each extension must be unique.
The technologies
and favicon
properties determine how your technology is presented on the Technology overview page.
To have data from your extension displayed on an existing technology tile, specify a matching technology name. You can look up current technology names in the ActiveGate extensions JSON reference or you can find them in the UI as the Main technology
process property.
The package name and class that is to be imported and executed by an ActiveGate correspond to the name of the Python file that contains the code and the name of the class that’s defined in it.
The metrics section describes the data gathered by the extension. This section provides two metrics that mirror both what our demo application serves, and what the Python code collects.
ConfigUI and the properties sections define the user interface elements used for extension configuration.
This part of the JSON file defines how metrics are charted. The key metrics section allows you to select the most important metrics and present them in the infographic and the group page. You'll find charts in the further details tab.
The Python code is stored in the demo_activegate_plugin_multi.py
file.
from ruxit.api.base_plugin import RemoteBasePluginfrom ruxit.api.data import PluginPropertyimport mathimport loggingfrom enum import Enumlogger = logging.getLogger(__name__)class RemoteExamplePlugin(RemoteBasePlugin):class State(Enum):DOWNTIME = 0MAINTENANCE = 1WORKING = 2def initialize(self, **kwargs):self.url = self.config.get("url", "http://127.0.0.1:8976")self.user = self.config.get("auth_user", "admin")self.password = self.config.get("auth_password", "admin")self.alert_interval = self.config.get("alert_interval", 10)self.event_interval = self.config.get("event_interval", 3)self.relative_interval = self.config.get("relative_interval", 60)self.state_interval = self.config.get("state_interval", 60)self.alert_iterations = 0self.event_iterations = 0self.relative_iterations = 0self.absolute_iterations = 0self.state_iterations = 0self.current_entries = 1self.archived_entries = 0def query(self, **kwargs):group_name = self.get_group_name()topology_group = self.topology_builder.create_group(group_name, group_name)topology_group.per_second("service.querries_per_second", self.get_num_querries())topology_group.report_property(key="group_property", value="group_property_value")devices = self.get_device_names()port = 80for device_name in devices:topology_device = topology_group.create_device(device_name, device_name)topology_device.state_metric("service.state_5", self.get_state_metric())topology_device.absolute("databases.total_num_entities", self.get_device_entries())table_size = 100topology_device.relative("databases.replicated_entries", self.get_archived_entries())for table in self.get_tables_for_device(device_name):topology_device.absolute("databases.table_size", table_size, {"table_name": table})table_size = table_size + 100if self.should_create_event():topology_device.report_custom_info_event("Custom event!")topology_device.report_performance_event("Performance problem description", "Performance problem", {})topology_device.report_property(key="device_property", value="device_property_value")topology_device.add_endpoint("127.0.0.1", port)port += 1def get_group_name(self):return "ExampleGroup"def get_state_metric(self):if self.state_iterations >= self.state_interval * 3:self.state_iterations = 0state = RemoteExamplePlugin.State(int(self.state_iterations / self.state_interval))self.state_iterations = self.state_iterations + 1return state.namedef get_num_querries(self):self.alert_iterations = self.alert_iterations + 1if self.alert_iterations > self.alert_interval:if self.alert_iterations > self.alert_interval + 3:self.alert_iterations = 0return 1return 7def get_device_names(self):return ["DeviceOne", "DeviceTwo"]def get_tables_for_device(self, device):if device == "DeviceOne":return ["d1_t1", "d1_t2", "d1_t3", "d2_t4"]return ["d2_t1", "d2_t2", "d2_t3", "d2_t4", "d2_t5", "d2_t6"]def get_device_entries(self):if self.absolute_iterations == 360:self.absolute_iterations = 0self.absolute_iterations = self.absolute_iterations + 1return self.current_entries + math.sin(math.radians(self.absolute_iterations))def get_archived_entries(self):self.relative_iterations = self.relative_iterations + 1if self.relative_iterations > self.relative_interval:self.relative_iterations = 0self.archived_entries = self.archived_entries + 1return self.archived_entriesdef should_create_event(self):self.event_iterations = self.event_iterations + 1if self.event_iterations > self.event_interval:self.event_iterations = 0return Truereturn False
The file defines the RemoteExamplePlugin
class, which in turn defines one method query. When your extension runs, this method is called once each minute to collect and send topology data and metrics to Dynatrace Server.
The demo app returns the JSON response as in the example below.
[{"nodes": [{"ip": "192.168.0.1","stats": {"stats_counter": [6, 10, 13],"random": 194,"state": "WARNING","counter": 4,"version": "1.001"},"name": "My Node 01"},{"ip": "127.0.0.1","stats": {"stats_counter": [7, 10, 11],"random": 194,"state": "WARNING","counter": 4,"version": "1.001"},"name": "My Node 02"}],"name": "My Group 01"}]
Plugin’s query method parses the response, finds groups and devices, and assigns metrics accordingly. The extension automatically detects and monitors new groups and devices.
This is just a beginning. Check other example extensions delivered with the SDK, explore How-tos, and get to know other deployment options. Your feedback matters. Post your questions and ideas for improvements to the Extensions section in the Dynatrace Community.