RousselTMLEARNING

Article · OpenObserve: from discovery to expertise

Installing OpenObserve

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' ./openobserve
GLIBC_2.xx not found error? We hit it on Debian 12. Use the -linux-amd64-musl archive, which does not depend on the glibc version.

2. Variables to know #

Everything is configured through the environment.

Main settings #

VariablePurposeDefault
ZO_DATA_DIRLocal data folder./data/openobserve/
ZO_LOCAL_MODESingle nodetrue
ZO_LOCAL_MODE_STORAGEdisk or s3disk
ZO_COMPACT_DATA_RETENTION_DAYSGlobal retention, minimum 3 days3650
ZO_INGEST_ALLOWED_UPTOMaximum age of accepted data, in hours5
ZO_PAYLOAD_LIMITMaximum request size209715200
ZO_NODE_ROLENode rolesall
ZO_TELEMETRYAnonymous telemetry to the vendortrue

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: minio

3. 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 .hits

What ingestion transforms #

These results were observed by sending {"Level":"INFO","http":{"status":500},"Tags":["a","b"]}:

SentStoredConsequence
LevellevelNames become lowercase
http.status (nested object)http_statusObjects 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 raise ZO_INGEST_ALLOWED_UPTO if needed.

📄 Installing OpenObserve and ingesting your first data →

My progress

  • ⏱ Estimated time : ≈ 8 min

Sign in to track your progress and take notes. Sign in

💬 Ask a question

Recommended Articles

Exploring data in OpenObserve: SQL, PromQL and VRL

Search with SQL, query metrics with PromQL, optimize a stream (indexes, partitions, retention) an...

Alerts and pipelines in OpenObserve

Create a template, a destination and an alert, avoid the SSRF webhook block and process data with...

Sending logs, metrics and traces to OpenObserve

OpenObserve receiving endpoints: JSON, bulk, OTLP with the OpenTelemetry Collector, Prometheus re...

OpenObserve: architecture and concepts

Understanding OpenObserve: Parquet storage, deployment modes, roles (router, ingester, querier, c...

OpenObserve in production: best practices

Choose your deployment mode, organize streams, secure, back up and monitor OpenObserve in product...

Feeding OpenSearch: ingest pipelines and Data Prepper

Transform data with ingest pipelines, collect with Data Prepper, receive OTLP and avoid the dynam...

Installing OpenSearch and OpenSearch Dashboards

Install OpenSearch with Docker Compose or the archive: initial password, vm.max_map_count, demo c...

Installer Grafana Tempo (Docker Compose, binaire et Helm)

Installer Grafana Tempo : configuration tempo.yaml, Docker Compose avec Grafana et Prometheus, po...

Grafana Alloy: Understanding and exploiting the User Interface (UI)

Discover how to enable, secure, and use Grafana Alloy's built-in web interface to visualize your ...

Support us

♥ SUPPORT US

Support RousselTM Learning

Courses, articles, labs and certificates stay free with no intrusive ads. A voluntary contribution, of any amount you choose, pays for hosting, lab environments and new content.

Contribute with PayPal Any amount · card or PayPal accountLearn more
QR code PayPal
Or scan this QR code with your phone

Thank you, every contribution counts!