openobserve/SKILL.md
OpenObserve (O2) — open-source observability platform for logs, metrics, traces, dashboards, alerts, and Real User Monitoring. Use when setting up OpenObserve (Docker, binary, Kubernetes), ingesting logs/metrics/traces via HTTP API, OpenTelemetry, Fluent Bit, Vector, or Prometheus remote_write, configuring streams and organizations, building dashboards, setting up alerts, integrating with OTEL Collector, or migrating from Elasticsearch, Datadog, or the Grafana/Loki/Prometheus stack. Fetch live documentation for up-to-date details.
npx skillsauth add mikkelkrogsholm/dev-skills openobserveInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
CRITICAL: Your training data for OpenObserve is unreliable. APIs change between versions and memorized patterns may be wrong or deprecated. Before writing any code, you MUST use
WebFetchto read the live docs:
WebFetch("https://openobserve.ai/docs/quickstart/")For specific topics (ingestion, alerts, pipelines, OTEL integration), fetch the relevant page from
https://openobserve.ai/docs/. Do not proceed without fetching first.
OpenObserve (O2) is a cloud-native observability platform built in Rust for logs, metrics, traces, dashboards, alerts, and Real User Monitoring — a self-hostable alternative to Datadog, Elasticsearch/Kibana, Splunk, and the Grafana/Loki/Prometheus stack. It achieves 140x lower storage costs than Elasticsearch through Parquet columnar storage and S3-native architecture.
OpenObserve consolidates what typically requires multiple tools into a single binary:
# Endpoint pattern: /api/{organization}/{stream_name}/_json
curl -u '[email protected]:Complexpass#123' \
-H 'Content-Type: application/json' \
http://localhost:5080/api/default/my_stream/_json \
-d '[{"level":"info","message":"hello","_timestamp":1697000000000000}]'
[OUTPUT]
Name http
Match *
URI /api/{organization}/{stream}/_json
Host localhost
Port 5080
tls Off
Format json
Json_date_key _timestamp
Json_date_format iso8601
HTTP_User [email protected]
HTTP_Passwd password
[OUTPUT]
Name es
Match *
Path /api/{organization}
Host localhost
index {stream}
Port 5080
tls Off
Suppress_Type_Name On
HTTP_User [email protected]
HTTP_Passwd password
remote_write:
- url: http://localhost:5080/api/default/prometheus/api/v1/write
queue_config:
max_samples_per_send: 10000
basic_auth:
username: [email protected]
password: password
POST /api/{organization}/traces
Configure your OTEL exporter to target http://localhost:5080/api/{org}/ with basic auth headers.
docker run -d \
--name openobserve \
-v $PWD/data:/data \
-p 5080:5080 \
-e ZO_ROOT_USER_EMAIL="[email protected]" \
-e ZO_ROOT_USER_PASSWORD="Complexpass#123" \
public.ecr.aws/zinclabs/openobserve:latest
UI is available at http://localhost:5080. Default org is default.
| Variable | Default | Purpose |
|---|---|---|
| ZO_ROOT_USER_EMAIL | — | Root user email (required on first start) |
| ZO_ROOT_USER_PASSWORD | — | Root user password (required on first start) |
| ZO_DATA_DIR | ./data/openobserve/ | Local data directory |
| ZO_S3_PROVIDER | — | Object storage provider: aws, gcs, minio, swift |
| ZO_S3_SERVER_URL | — | S3-compatible endpoint (required for MinIO/GCS) |
| ZO_S3_BUCKET_NAME | — | Storage bucket name |
| ZO_S3_ACCESS_KEY | — | Object storage access key |
| ZO_S3_SECRET_KEY | — | Object storage secret key |
| ZO_S3_REGION_NAME | — | Cloud region |
| ZO_MEMORY_CACHE_ENABLED | true | In-memory file caching |
| ZO_DISK_CACHE_ENABLED | true | Disk-based query caching |
The _timestamp field must be microseconds (not milliseconds or seconds). OpenObserve expects the _timestamp field in microseconds since Unix epoch. Sending milliseconds produces incorrect time ordering (data appears 1000x too old) without any error or warning. If omitted, OpenObserve auto-generates _timestamp at ingest time — but if your log already has a time field, map it explicitly and convert to microseconds. In Fluent Bit, set Json_date_format iso8601 and Json_date_key _timestamp and let OpenObserve parse ISO 8601, which avoids manual epoch conversion.
Streams are created automatically on first ingest — schema is inferred, not enforced. Sending data to /api/default/my_stream/_json creates the my_stream stream automatically if it does not exist. There is no PUT /stream step. The downside: if your first batch has inconsistent field types (e.g., level as integer in one record, string in another), the inferred schema may cause later query failures. Send a consistent payload on first ingest or define the schema explicitly in the UI before ingesting.
Every API endpoint is scoped to an organization — omitting or misspelling the org name creates a second isolated org. The URL pattern /api/{organization}/{stream}/_json requires the correct org slug. The default org created on first start is default. If you typo the org (e.g., /api/Default/ vs /api/default/), OpenObserve silently creates a new org and the data is invisible in the intended org's UI. Verify the org slug in the UI under IAM before configuring collectors.
Do not use local disk storage in production. The default ZO_DATA_DIR stores all stream data on local disk with no replication. A single disk failure loses all ingested data. For production, configure an S3-compatible backend (ZO_S3_PROVIDER, ZO_S3_BUCKET_NAME, etc.) before ingesting any data — there is no migration path from local disk to S3 after the fact. MinIO is a common self-hosted alternative if AWS S3 is not available.
Stream and organization names are case-sensitive and must use only lowercase alphanumeric characters and underscores. Names like MyApp-Logs or prod.errors will either be rejected or silently normalized, causing mismatch between your collector config and the UI. Stick to my_app_logs and prod_errors patterns. Org names follow the same rule — the default org is default (all lowercase).
Basic auth credentials must be base64-encoded for the Authorization header but most integrations support plain username/password fields. When using OpenTelemetry Collector or other integrations that require explicit HTTP headers, use Authorization: Basic <base64(user:pass)>. However, Fluent Bit's HTTP_User/HTTP_Passwd and Prometheus basic_auth block handle encoding automatically — do not double-encode. Mixing approaches is a common source of 401 errors.
development
Zod — TypeScript-first schema validation with static type inference. Use when building with Zod or asking about schema definitions, type inference, parsing, transformations, refinements, coercion, error handling, or integration with forms, APIs, or tRPC. Fetch live documentation for up-to-date details.
tools
Vite — next-generation frontend build tool with instant dev server and optimized production builds. Use when building with Vite or asking about its APIs, configuration, plugins, SSR, environment variables, or integration with frameworks. Fetch live documentation for up-to-date details.
tools
Upstash — serverless Redis, QStash, and Vector database with per-request pricing optimized for edge and serverless environments. Use when building with Upstash or asking about its Redis client, QStash message queuing, rate limiting, workflows, or vector search. Fetch live documentation for up-to-date details.
tools
Turso — edge-hosted SQLite database built on libSQL with embedded replicas, multi-tenancy, and low-latency global distribution. Use when building with Turso or asking about its libSQL client, embedded replicas, database-per-tenant patterns, auth tokens, sync, or integration with Drizzle or other ORMs. Fetch live documentation for up-to-date details.