From 33d1209ac94282d1afd977c48950fe2bad67754e Mon Sep 17 00:00:00 2001 From: M1 Date: Mon, 16 Mar 2026 14:00:29 +0400 Subject: [PATCH] feat: query language docs page at /dashboard/docs --- apps/web/src/dashboard/docs.html | 208 +++++++++++++++++++++++++++++++ apps/web/src/dashboard/home.html | 2 + apps/web/src/routes/dashboard.ts | 3 +- 3 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 apps/web/src/dashboard/docs.html diff --git a/apps/web/src/dashboard/docs.html b/apps/web/src/dashboard/docs.html new file mode 100644 index 0000000..51efeb1 --- /dev/null +++ b/apps/web/src/dashboard/docs.html @@ -0,0 +1,208 @@ + + + + + + PingQL — Query Language Docs + + + + + + + +
+ +

Query Language

+

A MongoDB-style query language for defining exactly when a monitor is up or down.

+ + +

Overview

+

A PingQL query is a JSON object that runs against every ping result. If the query evaluates to true, the monitor is considered up. Use $consider: "down" to invert this.

+

By default (no query set), a monitor is up when the HTTP status code is below 400.

+ + +

Fields

+

These are the values you can query against:

+ + + + + + + + + + + +
FieldTypeDescription
statusnumberHTTP status code (e.g. 200, 404)
bodystringFull response body as text
headers.namestringResponse header value (e.g. headers.content-type)
$responseTimenumberRequest latency in milliseconds
$certExpirynumberDays until SSL certificate expires
$jsonobjectJSONPath expression against response body — see below
$selectobjectCSS selector against response HTML — see below
+ + +

Operators

+ + + + + + + + + + + + + + + + +
OperatorDescriptionTypes
$eqEqual toany
$neNot equal toany
$gtGreater thannumber
$gteGreater than or equalnumber
$ltLess thannumber
$lteLess than or equalnumber
$containsString contains substringstring
$startsWithString starts withstring
$endsWithString ends withstring
$regexMatches regular expressionstring
$existsField is present and non-nullany
$inValue is in arrayany
+ + +

Basic Examples

+ +

Status code

+
// Up if status is 200
+{ "status": 200 }
+
+// Up if status is 2xx or 3xx
+{ "status": { "$lt": 400 } }
+ +

Response body

+
// Up if body contains "healthy"
+{ "body": { "$contains": "healthy" } }
+
+// Up if body matches a regex
+{ "body": { "$regex": "status.*(ok|healthy)" } }
+ +

Headers

+
// Up if response is JSON
+{ "headers.content-type": { "$contains": "application/json" } }
+ +

Response time

+
// Up if response is under 500ms
+{ "$responseTime": { "$lt": 500 } }
+ +

SSL certificate expiry

+
// Up if cert expires in more than 14 days
+{ "$certExpiry": { "$gt": 14 } }
+ + +

JSON Body — $json

+

Use $json to extract and compare a value from a JSON response body. The key is a dot-notation path, the value is a condition.

+
// Up if response JSON has { "status": "ok" }
+{ "$json": { "$.status": { "$eq": "ok" } } }
+
+// Up if search index has >= 1000 entries
+{ "$json": { "$.data.count": { "$gte": 1000 } } }
+
+// Nested path
+{ "$json": { "$.db.connections.active": { "$lt": 100 } } }
+ + +

HTML Parsing — $select

+

Use $select to extract text from an HTML response using a CSS selector. Useful for monitoring public-facing pages where there's no API.

+
// Up if h1 text is "Example Domain"
+{ "$select": { "h1": { "$eq": "Example Domain" } } }
+
+// Up if status badge contains "operational"
+{ "$select": { ".status-badge": { "$contains": "operational" } } }
+ + +

Logical Operators

+
// Up if status is 200 AND body contains "ok"
+{
+  "$and": [
+    { "status": 200 },
+    { "body": { "$contains": "ok" } }
+  ]
+}
+
+// Up if status is 200 OR 204
+{
+  "$or": [
+    { "status": 200 },
+    { "status": 204 }
+  ]
+}
+
+// Up if status is NOT 500
+{ "$not": { "status": 500 } }
+ + +

$consider — Inverting the Result

+

By default, a query returning true means the monitor is up. Set $consider: "down" to invert this — if the conditions match, the monitor is down.

+
// DOWN if response time exceeds 2 seconds
+{
+  "$consider": "down",
+  "$responseTime": { "$gt": 2000 }
+}
+
+// DOWN if cert expires in less than 7 days
+{
+  "$consider": "down",
+  "$certExpiry": { "$lt": 7 }
+}
+
+// DOWN if any of these match
+{
+  "$consider": "down",
+  "$or": [
+    { "status": { "$gte": 500 } },
+    { "$responseTime": { "$gt": 5000 } }
+  ]
+}
+ + +

Combining Multiple Queries

+

You can add multiple monitors pointing to the same URL with different queries — one for uptime, one for performance, one for content integrity.

+
// Monitor 1: basic uptime
+{ "status": { "$lt": 400 } }
+
+// Monitor 2: performance — down if slow
+{ "$consider": "down", "$responseTime": { "$gt": 1000 } }
+
+// Monitor 3: content — check API response shape
+{
+  "$and": [
+    { "status": 200 },
+    { "$json": { "$.ok": { "$eq": "true" } } }
+  ]
+}
+ + + +
+ + + + diff --git a/apps/web/src/dashboard/home.html b/apps/web/src/dashboard/home.html index 8dbe571..df8cc48 100644 --- a/apps/web/src/dashboard/home.html +++ b/apps/web/src/dashboard/home.html @@ -16,6 +16,8 @@