1. Installing OpenObserve #
Binary or Docker Compose.
With Docker Compose #
services:
openobserve:
image: public.ecr.aws/zinclabs/openobserve:latest
ports:
- "5080:5080"
environment:
ZO_DATA_DIR: /data
ZO_ROOT_USER_EMAIL: root@example.com
ZO_ROOT_USER_PASSWORD: Complexpass#123
volumes:
- o2-data:/data
volumes:
o2-data:docker compose up -d
curl http://localhost:5080/healthz
# {"status":"ok"}The UI is at http://localhost:5080. Root user credentials are only used at the first startup: changing them later in the file does not change the password.
With the binary #
ZO_ROOT_USER_EMAIL=root@example.com ZO_ROOT_USER_PASSWORD='Complexpass#123' ./openobserveGLIBC_2.xx not founderror? We hit it on Debian 12. Use the-linux-amd64-muslarchive, which does not depend on the glibc version.
2. Variables to know #
Everything is configured through the environment.
Main settings #
| Variable | Purpose | Default |
|---|---|---|
ZO_DATA_DIR | Local data folder | ./data/openobserve/ |
ZO_LOCAL_MODE | Single node | true |
ZO_LOCAL_MODE_STORAGE | disk or s3 | disk |
ZO_COMPACT_DATA_RETENTION_DAYS | Global retention, minimum 3 days | 3650 |
ZO_INGEST_ALLOWED_UPTO | Maximum age of accepted data, in hours | 5 |
ZO_PAYLOAD_LIMIT | Maximum request size | 209715200 |
ZO_NODE_ROLE | Node roles | all |
ZO_TELEMETRY | Anonymous telemetry to the vendor | true |
Storing in S3 or MinIO #
In local mode you can already move data off the disk. The local folder then keeps the WAL and temporary files.
ZO_LOCAL_MODE: "true"
ZO_LOCAL_MODE_STORAGE: s3
ZO_S3_SERVER_URL: http://minio:9000
ZO_S3_REGION_NAME: us-east-1
ZO_S3_BUCKET_NAME: openobserve
ZO_S3_ACCESS_KEY: minioadmin
ZO_S3_SECRET_KEY: minioadmin
ZO_S3_PROVIDER: minio3. First ingestion #
Sending and finding events.
Send #
The path is always /api/<organization>/<stream>/_json. The stream is created if it does not exist.
curl -u 'root@example.com:Complexpass#123' \
-H 'Content-Type: application/json' \
http://localhost:5080/api/default/commandes/_json \
-d '[
{"level":"error","service":"paiement","message":"timeout vers la banque","duree_ms":3100},
{"level":"info","service":"paiement","message":"ok","duree_ms":120},
{"level":"info","service":"panier","message":"ok","duree_ms":40}
]'
# {"code":200,"status":[{"name":"commandes","successful":3,"failed":0}]}Query #
The search API expects SQL and a time range in microseconds.
NOW=$(date +%s)
curl -s -u 'root@example.com:Complexpass#123' \
-H 'Content-Type: application/json' \
http://localhost:5080/api/default/_search \
-d "{\"query\":{
\"sql\":\"SELECT service, count(*) AS n, avg(duree_ms) AS moy FROM commandes GROUP BY service ORDER BY n DESC\",
\"start_time\":$(( (NOW-3600)*1000000 )),
\"end_time\":$(( (NOW+60)*1000000 )),
\"from\":0,\"size\":10}}" | jq .hitsWhat ingestion transforms #
These results were observed by sending {"Level":"INFO","http":{"status":500},"Tags":["a","b"]}:
| Sent | Stored | Consequence |
|---|---|---|
Level | level | Names become lowercase |
http.status (nested object) | http_status | Objects are flattened with _ |
Tags: ["a","b"] | String "[\"a\",\"b\"]" | An array becomes JSON text |
The old data pitfall: an event older than 5 hours is refused while still returning HTTP 200. The detail is in the response:"successful":0,"failed":1,"error":"Too old data...". So read the response body when backfilling, and raiseZO_INGEST_ALLOWED_UPTOif needed.
