Using CEL
FireHydrant allows you to query data and relationships in your Signals using Common Expression Language (CEL).
A basic query in FireHydrant includes an entity with properties available via dot notation (e.g., entity.property
) and logical operators with a comparison value. Today's only available entity is a Signal, which represents the incoming Event from webhooks. A basic query might look like the following:
// entity.property == "value"
signal.summary == "CPU Utilization Spiking"
Each Signal has properties that can be evaluated and a specific value you wish to express. CEL queries can be performed on the Signals list page and when creating Signals Rules for a team.
Basic CEL Usage
Logical Operators
Operator | Meaning | Examples returning true |
---|---|---|
== | Equals | 2 == 2 |
!= | Does not equal | 3 != 2 |
> | Greater than | 3 > 2 |
< | Less Than | 2 < 3 |
&& | And | 2 == 2 && 2 != 3 |
|| | Or | 2 == 3 || 2 == 2 |
CEL Functions
Function | Example |
---|---|
contains() | signal.summary.contains("CPU") |
matches() | signal.summary.matches("CPU") or matches(signal.summary, "CPU") |
size() | Check array length: size(signal.images) > 1 Check string length: size(signal.summary) > 3 |
startsWith() | signal.summary.startsWith("CPU") |
endsWith() | signal.summary.endsWith("Spiking") |
CEL Macros
Macro | Example | Definition |
---|---|---|
has() | has(signal.summary) | Tests whether a field is available |
all() | signal.all(x, has(x)) | Tests whether a predicate function holds for all properties of a signal |
exists() | signal.exists(x, has(x)) | Tests whether a predicate function holds for any properties of a signal |
map() | signal.links.map(link, link.url != "") | Maps a list and provides each value to be mapped and returned in a new list |
filter() | signal.images.map(image, image.src != "") | Filters a list and provides matching values to be returned in a new list |
Note:
📚 You can check out the full documentation of CEL to explore even more about leveraging CEL inside of FireHydrant for querying signals.
Example Signal and CEL Query
{
"summary": "CPU Utilization Spiking",
"body": "The production server is experiencing greater than 99% utilizations of compute.",
"level": 0,
"status": 0,
"images": [
{
"src": "https://site.com/images/123.png",
"alt": "A simple, sample image"
}
],
"links": [
{
"href": "https://site.com/monitors/123",
"text": "Monitoring Source"
}
],
"annotations": {
"policy": "escalatable"
},
"tags": ["service:core-application", "env:prod"],
"received_at": "2023-11-09T18:22:16.000+00:00"
}
Below is an example CEL expression that would return true on this payload:
signal.summary.contains("CPU") && signal.level == 2 && signal.annotations.policy.equals("escalatable")
In this expression:
signal
refers to the instance of the Signal.signal.summary
checks if the summary field in the Signal message contains "CPU".signal.level checks
if the level field in the Signal message equals the enum for “ERROR”. The standard system levels are available here: INFO: 0 , WARN: 1, ERROR: 2, & FATAL: 3signal.annotations.policy.equals('escalatable')
accesses apolicy
key and checks if it equals "escalatable." If the key doesn't exist, then this value will automatically evaluate tofalse
☝️ Note about Signals Levels
Signals can take on a standard “Level” based on data from a webhook. You can run CEL queries based on the ENUM value for each, as shown below.
INFO = 0;
WARN = 1;
ERROR = 2;
FATAL = 3;
Other Resources
Updated 6 months ago