Programmable Configuration
You can write simple Velocity scripts to automatically configure your monitoring resources by pulling data from an HTTP portal (like NetBox), reading local files, SQL databases, running local commands, or parsing JSON content. Templates can also be re-evaluated on a schedule to keep the configuration in sync with these sources.
This is ideal for:
- Large environments with hundreds or thousands of resources
- Dynamic infrastructures where resources are frequently added or removed
- Integration with CMDBs or inventory systems
The following Velocity Tools are supported to fetch and transform data into valid configuration blocks:
| Tool | Purpose |
|---|---|
$http | Making HTTP requests to APIs |
$file | Reading local files |
$json | Parsing JSON data |
$collection | Splitting strings or manipulating collections |
$sql | Executing SQL queries on a database |
$command | Executing local commands and scripts |
$env | Retrieving environment variables |
$schedule | Scheduling the re-evaluation of the template |
$date, $number, $esc | Date formatting, number formatting, escaping |
Writing Velocity Templates
- Connect to the Web Interface at
https://MACHINE_WHERE_METRICSHUB_IS_RUNNING:31888 - Click Tools > YAML Editor, then Create > New Velocity template
- In the editor, write your Velocity script to either load resources from:
- Click Test to validate your script and preview the generated configuration blocks
- Click Save
- When ready, click Apply.
In Velocity, use # for directives, ## for comments, and $ for variables.
Loading Resources
From an HTTP API
Use the $http.execute(...) function to execute HTTP requests directly from templates.
$http.execute Tool Arguments
| Argument | Description |
|---|---|
url | (Required) The HTTP(S) endpoint to call. |
method | HTTP method (GET, POST, etc.). (Default: GET). Use $http.get(...) or $http.post(...) to quickly send GET or POST requests without specifying a method |
username | Username used for authentication. |
password | Password used for authentication. |
headers | HTTP headers, written as newline-separated Key: Value pairs. |
body | Payload to send with the request (e.g., for POST). |
timeout | Request timeout in seconds. (Default: 60). |
Example
Suppose your API endpoint at https://cmdb/servers returns:
[
{ "hostname": "host1", "OSType": "win", "adminUsername": "admin1" },
{ "hostname": "host2", "OSType": "win", "adminUsername": "admin2" }
]
You can dynamically create resource blocks using:
resources:
#set($hostList = $json.parse($http.get({ "url": "https://cmdb/servers" }).body).root())
#foreach($host in $hostList)
#if($host.OSType == "win")
$host.hostname:
attributes:
host.name: $host.hostname
host.type: windows
protocols:
ping:
wmi:
timeout: 120
username: $host.adminUsername
password: $http.get({ "url": "https://passwords/servers/${host.hostname}/password" }).body
#end
#end
From a Local File
Use the $file.readAllLines(filePath) function to read all lines from a local file.
$file.readAllLines Tool Arguments
| Argument | Description |
|---|---|
filePath | (Required) The path to the local file. |
Example
If your CSV file contains:
host1,win,wmi,user1,pass1
host2,linux,ssh,user2,pass2
Use this Velocity template to generate the resource block:
#set($lines = $file.readAllLines("/opt/data/resources.csv"))
resources:
#foreach($line in $lines)
#set($fields = $collection.split($line))
#set($hostname = $fields.get(0))
#set($hostType = $fields.get(1))
#set($protocol = $fields.get(2))
#set($username = $fields.get(3))
#set($password = $fields.get(4))
$hostname:
attributes:
host.name: $hostname
host.type: $hostType
protocols:
$protocol:
username: $username
password: $password
#end
From an SQL Database
Use the $sql.query(query, jdbcUrl, username, password, timeout) function to execute SQL queries.
$sql.query Tool Arguments
| Argument | Description |
|---|---|
query | (Required) SQL query to execute. |
jdbcUrl | (Required) The JDBC connection URL to access the database. |
username | Name used for database authentication. |
password | Password used for database authentication. |
timeout | (Optional) Query timeout in seconds (Default: 120). |
Example
Consider a hosts table in your database with the following data:
| hostname | host_type | username | password |
|---|---|---|---|
| storage-server-1 | storage | admin1 | pwd1 |
| windows-server-1 | windows | admin2 | pwd2 |
You can dynamically create resource blocks by querying the database:
#set($url = "jdbc:h2:mem:management_db")
#set($user = "sa")
#set($pass = "pwd1")
#set($rows = $sql.query("SELECT hostname, host_type, username, password FROM hosts ORDER BY hostname", $url, $user, $pass, 120))
resources:
#foreach($row in $rows)
#set($hostname = $row.get(0))
#set($host_type = $row.get(1))
#set($username = $row.get(2))
#set($password = $row.get(3))
#if($host_type.equals("storage"))
$hostname:
attributes:
host.name: $hostname
host.type: $host_type
protocols:
http:
hostname: $hostname
https: true
port: 443
username: $username
password: $password
#end
#end
From a Command Line
Use the $command.execute(...) function to run a local command or script (a discovery script, a cloud CLI such as aws, az or kubectl, an inventory tool, etc.) and build your resources from its output.
The command is executed through the system shell (cmd.exe /C on Windows, $SHELL -c or /bin/sh -c on Linux/UNIX), so pipes, redirections and && are supported.
You can call it either with the command line only:
#set($result = $command.execute("/opt/scripts/list-hosts.sh"))
or with a map of arguments:
#set($result = $command.execute({
"command": "/opt/scripts/list-hosts.sh",
"timeout": "30",
"workingDirectory": "/opt/scripts",
"failOnError": "true"
}))
$command.execute Tool Arguments
| Argument | Description |
|---|---|
command | (Required) The command line to execute. |
timeout | Execution timeout in seconds. The command and its child processes are killed when the timeout is reached. (Default: 60). |
workingDirectory | Directory from which the command is executed. (Default: the working directory of MetricsHub). |
charset | Charset used to decode the command output (e.g., UTF-8, ISO-8859-1, Cp850). (Default: UTF-8). |
env | Additional environment variables, written as newline-separated KEY=VALUE pairs. They are added to the environment inherited from MetricsHub. |
failOnError | Set to true to make the template fail when the command exits with a non-zero code. The error is then reported in the Web Interface. (Default: false). |
Result
$command.execute(...) returns an object with the following properties:
| Property | Description |
|---|---|
stdout | The standard output of the command. |
stderr | The standard error output of the command. |
exitCode | The exit code of the command (0 = success). |
When failOnError is false (default), a command exiting with a non-zero code does not stop the template: a warning is logged, and you can check $result.exitCode to handle the failure in your template.
Example
Suppose the /opt/scripts/list-hosts.sh script returns one hostname per line:
host1
host2
You can dynamically create resource blocks using:
#set($result = $command.execute({ "command": "/opt/scripts/list-hosts.sh", "timeout": "30" }))
resources:
#if($result.exitCode == 0)
#foreach($line in $result.stdout.split("\n"))
#set($hostname = $line.trim())
#if(!$hostname.isEmpty())
$hostname:
attributes:
host.name: $hostname
host.type: linux
protocols:
ssh:
username: admin
password: $env.get("SSH_PASSWORD")
#end
#end
#end
If the command returns JSON, combine it with the $json tool:
#set($nodeList = $json.parse($command.execute("kubectl get nodes -o json").stdout).root())
To pass environment variables to the command, use the env argument. Like the headers argument of $http.execute, env is a string (not a map) containing one KEY=VALUE pair per line:
#set($result = $command.execute({
"command": "/opt/scripts/list-hosts.sh",
"env": "INVENTORY_URL=https://cmdb/api"
}))
To pass several variables, put each KEY=VALUE pair on its own line within the string (leading spaces are ignored, so you can indent the lines):
#set($result = $command.execute({
"command": "/opt/scripts/list-hosts.sh",
"env": "INVENTORY_URL=https://cmdb/api
INVENTORY_SITE=paris"
}))
Commands are executed on the machine where MetricsHub is running, with the privileges of the account running MetricsHub. Only use commands and scripts you trust, and restrict write access to your Velocity templates accordingly.
Using Environment Variables
Use $env.get("ENV_VARIABLE_NAME") to retrieve environment variables in your templates:
#set($apiKey = $env.get("CMDB_API_KEY"))
#set($response = $http.get({
"url": "https://cmdb/api/servers",
"headers": "Authorization: Bearer $apiKey"
}))
This allows you to keep sensitive credentials out of your template files.
Re-evaluating Templates on a Schedule
By default, a Velocity template is evaluated only when MetricsHub starts and whenever the template file is modified. However, the data returned by $http, $sql, $file or $command may change while the template itself does not (e.g., a new host is added to your CMDB).
Use $schedule.cron(...) to have MetricsHub re-evaluate the template periodically:
## Re-evaluate this template every 15 minutes
$schedule.cron("0 */15 * * * *")
Each time the schedule fires, the whole template is evaluated again from scratch: every $http, $sql, $file and $command call is run again. If the generated configuration differs from the previous one, MetricsHub automatically reloads its configuration to apply the changes. If the result is unchanged, nothing is reloaded.
$schedule.cron Tool Arguments
| Argument | Description |
|---|---|
cronExpression | (Required) The cron expression that defines when the template is re-evaluated. |
The cron expression is made of 6 fields: second minute hour day-of-month month day-of-week. The @hourly, @daily, @weekly, @monthly and @yearly macros are also accepted.
| Cron expression | Re-evaluation |
|---|---|
0 */5 * * * * | Every 5 minutes |
0 0 * * * * | Every hour |
0 0 6 * * * | Every day at 6:00 AM |
0 0 8 * * MON-FRI | Every weekday at 8:00 AM |
@daily | Every day at midnight |
$schedule.cron(...)prints nothing in the generated configuration and can be placed anywhere in the template.- A template can only have one schedule. If
$schedule.cron(...)is called several times, only the last expression is applied and a warning is logged. - An invalid cron expression is logged as an error and ignored. The other templates keep being re-evaluated normally.
- Removing
$schedule.cron(...)from a template stops its periodic re-evaluation. New or deleted templates are taken into account without restarting MetricsHub.
Example
The template below queries the CMDB every hour and automatically adds or removes the corresponding resources:
$schedule.cron("0 0 * * * *")
resources:
#set($hostList = $json.parse($http.get({ "url": "https://cmdb/servers" }).body).root())
#foreach($host in $hostList)
$host.hostname:
attributes:
host.name: $host.hostname
host.type: $host.OSType
protocols:
ping:
#end
Re-evaluating a Template on Demand
To re-evaluate a template immediately, without waiting for its schedule:
- Connect to the Web Interface
- Click Tools > YAML Editor and select the Velocity template (
.vm) - Click Reevaluate.
The template is evaluated again, and the running configuration is reloaded only if the result has changed.