Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pixlcore/xyops/llms.txt

Use this file to discover all available pages before exploring further.

xyOps uses a custom expression language built on JEXL (JavaScript Expression Language) with custom helper functions and Mustache-style string interpolation.

Overview

The xyOps Expression Format powers multiple subsystems:
  • Monitor Expressions - Define custom metrics from server data
  • Alert Trigger Expressions - Conditional logic for alert firing
  • Alert Messages - Dynamic message templates
  • Plugin Parameters - Runtime parameter expansion
  • Workflow Decision Controllers - Branch logic in workflows
  • Workflow Split Controllers - Fan-out patterns
  • Web Hook Messages - Dynamic webhook payloads
  • Email Templates - Personalized notifications
Expressions use JavaScript-style syntax with dot notation, array indexing, and standard operators.

Expression Examples

// Extract memory RSS for ffmpeg processes
processes.list[.command == 'ffmpeg'].memRss

JEXL Syntax

xyOps expressions support full JEXL syntax:

Object Traversal

// Dot notation
cpu.currentLoad

// Deep paths
processes.list[0].memRss

// Dynamic access
server[groupName]

Array Operations

// Filter arrays
processes.list[.command == 'node']

// Multiple filters
processes.list[.command == 'node' && .memRss > 500000000]

// Access by index
processes.list[0].pid

Operators

memory.used + memory.cached
memory.total - memory.available
cpu.cores * 2
memory.used / memory.total
memory.usedPercent % 10
cpu.currentLoad > 80
memory.available < 1000000000
monitors.load_avg >= cpu.cores
processes.list.length <= 100
job.code == 0
status != 'running'
// AND
cpu.currentLoad > 80 && memory.usedPercent > 90

// OR
job.code == 1 || job.code == 2

// NOT
!alert.cleared
job.code == 0 ? 'Success' : 'Failed'
cpu.cores > 4 ? 'high' : 'low'

Custom Helper Functions

xyOps extends JEXL with custom functions for common operations:

Math and Array Functions

min
function
Returns the minimum value.
min(4, 5) == 4
min(cpu.load1, cpu.load5, cpu.load15)
max
function
Returns the maximum value.
max(4, 5) == 5
max(memory.used, memory.cached)
floor
function
Rounds down to nearest integer. See Math.floor.
floor(1.9) == 1
floor(cpu.currentLoad)
ceil
function
Rounds up to nearest integer. See Math.ceil.
ceil(1.1) == 2
ceil(memory.usedPercent)
round
function
Rounds to nearest integer. See Math.round.
round(1.5) == 2
round(cpu.currentLoad)
clamp
function
Clamps a value between min and max.
clamp(50, 0, 100) == 50
clamp(150, 0, 100) == 100
clamp(cpu.currentLoad, 0, 100)
count
function
Returns the number of items in an array.
count(processes.list)
count(servers.active)
Use count() instead of .length in JEXL expressions.
find
function
Finds objects in an array using property and substring match.
find(processes.list, 'command', 'node')
find(servers, 'hostname', 'prod')
includes
function
Checks if string contains substring or array contains element.
includes('hello world', 'world') == true
includes(tags, 'production')

String Formatting Functions

bytes
function
Formats byte count as human-readable size.
bytes(1048576) == "1 MB"
bytes(memory.total)
Examples:
  • bytes(1024)"1 KB"
  • bytes(1073741824)"1 GB"
  • bytes(memory.available)"4.2 GB"
number
function
Formats number with locale-specific separators.
number(1048576) == "1,048,576"
number(processes.list.length)
pct
function
Formats percentage given value and maximum.
pct(0.5, 1.0) == "50%"
pct(memory.used, memory.total)
integer
function
Extracts integer from string.
integer("123abc") == 123
integer("42.7") == 42
float
function
Shortens float to 2 decimal places.
float(1.33333333) == "1.33"
float(cpu.currentLoad)
encode
function
URL-encodes a string. See encodeURIComponent.
encode("hello world") == "hello%20world"
encode(alert.message)
stringify
function
Serializes object to JSON string. See JSON.stringify.
stringify({a: 1, b: 2}) == "{\"a\":1,\"b\":2}"
stringify(job.params)

Mustache String Interpolation

Alert messages and templates support {{ }} style interpolation:
// Alert message template
Server {{server.hostname}} has {{pct(memory.used, memory.total)}} memory usage

// With nested expressions
{{bytes(memory.available)}} of {{bytes(memory.total)}} available

// Job hook template
Job {{job.id}} completed on {{nice_server}} with result: {{job.code}}
Mustache syntax is only available in string contexts (messages, templates). Use regular JEXL syntax for conditional expressions.

Common Use Cases

Monitor Expressions

Define custom metrics from server data:
cpu.avgLoad / cpu.cores

Alert Trigger Conditions

Determine when alerts should fire:
monitors.load_avg >= (cpu.cores + 1)

Alert Messages

Generate dynamic, informative messages:
// Memory alert
Less than {{pct(memory.available, memory.total)}} memory available ({{bytes(memory.available)}} of {{bytes(memory.total)}})

// CPU alert
CPU load average ({{float(monitors.load_avg)}}) exceeds core count ({{cpu.cores}})

// Disk alert
Disk {{filesystem.mount}} is {{float(filesystem.usePercent)}}% full ({{bytes(filesystem.used)}} used)

// Process alert
Process {{process.command}} is using {{bytes(process.memRss)}} of memory

Workflow Decisions

Control workflow branching:
job.code == 0

Data Context

Expressions have access to different data contexts depending on where they’re used:
Access to ServerMonitorData:
cpu.currentLoad
memory.available
processes.list
filesystem.list
network.interfaces
Access to server data plus monitor values:
monitors.cpu_usage
monitors.load_avg
monitors.memory_used
cpu.cores
memory.total
Access to JobHookData:
job.id
job.code
job.description
event.title
event.id
server.hostname
nice_server
links.job_details
Access to AlertHookData:
alert.id
alert.message
def.title
def.expression
server.hostname
nice_server
links.alert_url

Best Practices

1

Keep expressions simple

Complex logic is harder to debug. Break down into smaller monitors when possible.
// Good
monitors.cpu_high && monitors.memory_high

// Less maintainable
(cpu.currentLoad > 80 && cpu.avgLoad > cpu.cores * 0.8) && (memory.usedPercent > 85 && memory.available < 1000000000)
2

Use helper functions

Leverage built-in formatters for readability:
// Good
bytes(memory.available)

// Bad
memory.available + ' bytes'
3

Handle missing data

Use defaults or conditional checks:
// Safe
count(processes.list[.command == 'nginx']) > 0

// May fail if processes undefined
processes.list[.command == 'nginx'].length > 0
4

Test expressions

Use the expression tester in the UI to validate before deploying.

References