Skip to content

Logs quickstart

By the end of this guide you’ll have ingested a few logs, queried them via the API, and pinned a saved view in the dashboard.

Terminal window
curl -X POST https://logs.siteqwality.com/v1/ingest \
-H "Authorization: Bearer $SITEQWALITY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
"level": "error",
"message": "Failed to charge card",
"source": "billing-api",
"env": "prod",
"host": "api-demo-1",
"tags": { "endpoint": "/api/charge" },
"metadata": {
"user_id": "usr_abc123",
"amount_cents": 9900,
"stripe_error": "card_declined"
}
}'

202 Accepted. The log appears in ClickHouse within ~10 seconds.

Terminal window
for i in {1..20}; do
LEVEL="info"
[ $((i % 5)) -eq 0 ] && LEVEL="error"
curl -X POST https://logs.siteqwality.com/v1/ingest \
-H "Authorization: Bearer $SITEQWALITY_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",
\"level\": \"$LEVEL\",
\"message\": \"Order $i processed\",
\"source\": \"billing-api\",
\"env\": \"prod\",
\"tags\": { \"endpoint\": \"/api/orders\" }
}" > /dev/null
sleep 2
done

That’s 20 logs over 40 seconds, with 4 errors mixed in.

Logs → Explorer. Filter source = billing-api, level = error. The matching logs render in a table with the message and metadata expanded.

In the dashboard’s Logs Explorer, after applying your filters click Save view, name it Billing errors (prod). It now appears in the Saved views sidebar; share with your team by toggling Shared.

Or via the API:

Terminal window
curl -X POST https://api.siteqwality.com/log_saved_views \
-H "Authorization: Bearer $SITEQWALITY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Billing errors (prod)",
"description": "All errors from billing-api in prod",
"is_shared": true,
"filters": {
"source": "billing-api",
"env": "prod",
"level": "error"
}
}'

Most logging libraries can ship to a HTTP sink. Two common patterns:

Direct ship from your app (small services):

import logging, requests, json, os
class SqHandler(logging.Handler):
def emit(self, record):
requests.post(
"https://logs.siteqwality.com/v1/ingest",
headers={"Authorization": f"Bearer {os.environ['SITEQWALITY_API_KEY']}"},
json={
"timestamp": record.created,
"level": record.levelname.lower(),
"message": record.getMessage(),
"source": "my-app",
},
timeout=2,
)

Ship via your existing log pipeline (Vector, Fluent Bit, Filebeat). Point it at https://logs.siteqwality.com/v1/ingest with the API key in the Authorization header.

For high-volume apps, batch via NDJSON: stick to Content-Type: application/x-ndjson and submit one JSON object per line, up to ~1MB per request.