OpenObserve v1.1.1 API 使用详解
面向需要用 API 集成或运维 OpenObserve 的工程师,逐域讲清 v1.1.1 的认证、日志摄入、查询、流管理、仪表盘、告警、用户与函数 API:端点、方法、请求体、实测响应与错误处理。全部请求与回显均在 Ubuntu 22.04.4 LTS(x86_64)+ OpenObserve v1.1.1(开源单机模式)实测通过。
OpenObserve v1.1.1 API 使用详解
> 目标:面向需要用 API 集成或运维 OpenObserve 的工程师,逐域讲清 v1.1.1 的认证、日志摄入、查询、流管理、仪表盘、告警、用户与函数 API:端点、方法、请求体、实测响应与错误处理。全部请求与回显均在 Ubuntu 22.04.4 LTS(x86_64)+ OpenObserve v1.1.1(开源单机模式)实测通过。
一、环境信息
本文所有命令与回显的实测环境:
- 操作系统:Ubuntu 22.04.4 LTS(x86_64)
- OpenObserve:v1.1.1(开源版单机,
/config实测"build_type": "opensource") - API 基址:
http://localhost:5080(HTTP 与 Web 控制台共用 5080) - 组织(org_id):
default(首次启动自动创建的默认组织) - 管理账号:
root@example.com/Q1w2E3r4!(演示凭据) - 样本流:
app_logs(已摄入 5 条应用日志,含 level/job/message/status/duration_ms/host 字段)
二、前置条件
- 一个可访问的 OpenObserve v1.1.1 实例(部署见《OpenObserve Docker Compose 部署指南》);
- 具备 API 调用权限的账号(root 或 admin 角色);
- 熟悉 curl 基本用法;本文所有示例直接用 curl,语言绑定(Python/Go SDK)按官方 API 契约同理封装。
URL 结构约定:除少数根路径端点(如 /auth/login)外,API 一律挂在组织之下:
/api/{org_id}/{资源}
实测中 org_id 一律用 default。
三、认证与首次调用
3.1 HTTP Basic 认证(推荐给 API 调用)
官方 API 索引明确:所有 API 使用 HTTP Basic 认证(Authorization: Basic base64(用户名:密码)),curl 的 -u 参数即等价实现。首次调用验证:
curl -s -u "root@example.com:Q1w2E3r4!" http://localhost:5080/api/default/streams -o /dev/null -w "%{http_code}\n"
实测回显:
200
不带凭据访问受保护 API:
curl -s -i http://localhost:5080/api/default/streams | head -4
实测回显:
HTTP/1.1 401 Unauthorized
content-type: application/json
x-api-node: 9f4e7b5c706a
vary: origin, access-control-request-method, access-control-request-headers
3.2 会话登录(Web 控制台流程)
/auth/login 用于生成会话 Cookie(浏览器流程),API 集成直接用 Basic 即可:
curl -s -X POST http://localhost:5080/auth/login \
-H "Content-Type: application/json" \
-d '{"name":"root@example.com","password":"Q1w2E3r4!"}'
实测回显:
{"status":true,"message":""}
四、日志摄入 API
v1.1.1 提供 4 条日志摄入通道,均自动建流(Stream)并推断 schema。
4.1 JSON 批量摄入(/api/{org}/{stream}/_json)
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST "http://localhost:5080/api/default/app_logs/_json" \
-H "Content-Type: application/json" \
-d '[
{"level":"info","job":"api-gateway","message":"POST /api/v1/orders 200 in 12ms","status":200,"duration_ms":12,"host":"web-01"},
{"level":"warn","job":"api-gateway","message":"GET /api/v1/cart slow response","status":200,"duration_ms":860,"host":"web-01"},
{"level":"error","job":"payment","message":"upstream timeout while charging","status":504,"duration_ms":3005,"host":"pay-02"},
{"level":"info","job":"payment","message":"charge succeeded order=A-1024","status":200,"duration_ms":45,"host":"pay-02"},
{"level":"info","job":"auth","message":"user login ok uid=1001","status":200,"duration_ms":8,"host":"auth-01"}
]'
实测回显:
{"code":200,"status":[{"name":"app_logs","successful":5,"failed":0}]}
successful/failed 是 ingestion 监控的关键指标。
4.2 逐行摄入(/api/{org}/{stream}/_multi)
每行一条 JSON 记录(NDJSON):
printf '{"level":"error","job":"cron","message":"replica lag 120s","host":"db-02"}\n' > /tmp/m2.log
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST "http://localhost:5080/api/default/cron_logs/_multi" \
-H "Content-Type: application/json" \
--data-binary @/tmp/m2.log
实测回显:
{"code":200,"status":[{"name":"cron_logs","successful":1,"failed":0}]}
排障实录:该端点按行解析 JSON。若按传统 syslog/logfmt 思路发纯文本行(如 level=info job=cron ...),返回 400:
{"code":400,"message":"Error# Failed processing: JsonError(Error(\"expected value\", line: 1, column: 1))"}
结论:_multi 不做 logfmt 转换,文本类日志需在客户端(Vector/Fluent-bit)转成 JSON 再推。
4.3 Elasticsearch Bulk 兼容摄入(/api/{org}/_bulk)
NDJSON 协议(动作行 + 数据行交替),Filebeat/Logstash 等 ES 采集器可零改造切换:
printf '{"create":{"_index":"bulk_logs"}}\n{"level":"info","message":"bulk record one","host":"es-01"}\n{"create":{"_index":"bulk_logs"}}\n{"level":"warn","message":"bulk record two","host":"es-02"}\n' > /tmp/b.ndjson
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST "http://localhost:5080/api/default/_bulk" \
-H "Content-Type: application/json" \
--data-binary @/tmp/b.ndjson
实测回显(逐条确认创建成功,ES 风格响应结构):
{"took":0,"errors":false,"items":[{"index":{"_index":"bulk_logs","_id":"","_version":1,"result":"created","_shards":{"total":1,"successful":1,"failed":0},"_seq_no":1,"_primary_term":1,"status":200}},{"index":{"_index":"bulk_logs","_id":"","_version":1,"result":"created","_shards":{"total":1,"successful":1,"failed":0},"_seq_no":1,"_primary_term":1,"status":200}}]}
4.4 OTLP 日志摄入(/api/{org}/v1/logs)
OpenTelemetry 协议(JSON 编码的 ResourceLogs 结构):
cat > /tmp/otlp.json << 'EOF'
{"resourceLogs":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"demo-app"}}]},"scopeLogs":[{"logRecords":[{"timeUnixNano":"1792297000000000000","severityText":"INFO","body":{"stringValue":"otlp demo log from demo-app"},"attributes":[{"key":"env","value":{"stringValue":"prod"}}]}]}]}]}
EOF
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST "http://localhost:5080/api/default/v1/logs" \
-H "Content-Type: application/json" \
--data-binary @/tmp/otlp.json
实测回显:
{}
返回空对象且 HTTP 200 表示接收成功(OTLP 风格的静默确认);数据落入 default 流(OTLP 日志的默认落流,可用 _search 查 service.name、severity 等自动展开字段验证)。
五、查询 API
5.1 SQL 查询(/api/{org}/_search)
请求体三要素:sql、start_time、end_time(微秒时间戳):
NOW=$(date +%s)
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST "http://localhost:5080/api/default/_search" \
-H "Content-Type: application/json" \
-d "{\"query\":{\"sql\":\"SELECT level, job, message, duration_ms FROM app_logs ORDER BY duration_ms DESC LIMIT 3\",\"start_time\":$(( (NOW-3600)*1000000 )),\"end_time\":$(( NOW*1000000 ))}}"
实测回显(节选):
{"took":9,"took_detail":{"total":9,"cache_took":0,"file_list_took":0,"wait_in_queue":0,"idx_took":0,"search_took":8},"hits":[{"_timestamp":1792296280528199,"level":"error","job":"payment","message":"upstream timeout while charging","duration_ms":3005},{"_timestamp":1792296280528198,"level":"warn","job":"api-gateway","message":"GET /api/v1/cart slow response","duration_ms":860},{"_timestamp":1792296280528199,"level":"info","job":"payment","message":"charge succeeded order=A-1024","duration_ms":45}],"total":3,"from":0,"size":3,"cached_ratio":0,"scan_size":0,"idx_scan_size":0,"scan_records":5,"is_partial":false}
响应要点:
| 字段 | 含义 |
|---|---|
hits | 命中记录数组,_timestamp(微秒)为内置时间字段 |
total / from / size | 总命中数与分页游标 |
took_detail | 各阶段耗时(缓存命中、文件列表、排队、索引、检索) |
scan_records / scan_size | 实际扫描记录数与字节数(成本观测) |
is_partial | 是否部分结果(超时/分片未完成时为 true) |
聚合查询同理,例如每分钟日志量直方图:
SELECT histogram(_timestamp, '1 minute') AS t, count(*) AS c FROM app_logs GROUP BY t ORDER BY t
5.2 值列表与上下文接口(v1.1.1 实测说明)
控制台的"字段值分布"(_values)与"上下文浏览"(_around)在 v1.1.1 开源单机实测直接访问 /api/default/_values、/api/default/_around 及流级变体均返回 404 Not Found(未开放或路径变更);等价能力可用 _search 自行实现:
- 字段值分布:
SELECT level, count(*) AS c FROM app_logs GROUP BY level - 上下文定位:
SELECT * FROM app_logs WHERE _timestamp BETWEEN a AND b ORDER BY _timestamp
💡 说明:控制台页面正常提供这些视图(由内部端点支撑),API 使用方在 v1.1.1 以
_search聚合替代即可,升级版本后可再核对官方 API 索引。
六、流管理 API
6.1 流列表(GET /api/{org}/streams)
curl -s -u "root@example.com:Q1w2E3r4!" "http://localhost:5080/api/default/streams"
实测回显(节选):
{"list":[{"name":"app_logs","storage_type":"disk","stream_type":"logs","stats":{"created_at":1792293071331959,"doc_time_min":1792293071331959,"doc_time_max":1792293071332965,"doc_num":5,"file_num":1,"storage_size":0.0007219314575195312,"compressed_size":0.0025720596313476562,"index_size":0.004790306091308594,"mindex_size":0.0},"schema":[],"settings":{"partition_keys":{},"full_text_search_keys":["m
stats 提供文档数、存储/索引体量,适合做容量监控;doc_num:5 与摄入记录一致。
6.2 流 Schema(GET /api/{org}/streams/{stream}/schema)
curl -s -u "root@example.com:Q1w2E3r4!" "http://localhost:5080/api/default/streams/app_logs/schema"
实测回显(节选):
{"name":"app_logs","storage_type":"disk","stream_type":"logs","stats":{...},"schema":[{"name":"_timestamp","type":"Int64"},{"name":"duration_ms","type":"Int
schema 数组即摄入时自动推断的字段类型(Int64/String 等),接入前可用它核对字段名大小写(OpenObserve 字段名大小写敏感)。
6.3 删除流(DELETE /api/{org}/streams/{stream})
curl -s -u "root@example.com:Q1w2E3r4!" -X DELETE http://localhost:5080/api/default/streams/bulk_logs
实测回显:
{"code":200,"message":"stream deleted"}
删除不存在的流:
{"code":404,"message":"stream not found"}
⚠️ 注意:删除流同时清除其数据与元信息,不可恢复;
triggers等系统内置流不要删除。
七、仪表盘 API
仪表盘(Dashboard)的请求/响应采用版本化信封(v8 为 v1.1.1 的仪表盘结构版本)。
7.1 创建(POST /api/{org}/dashboards)
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST http://localhost:5080/api/default/dashboards \
-H "Content-Type: application/json" \
-d '{"title":"api-demo-dash","description":"created by API doc test"}'
实测回显(节选):
"dashboardId":"7517438982746013696","title":"api-demo-dash","description":"created by API doc test"
返回 dashboardId(服务端生成的数字 ID)。
7.2 查询单个(GET /api/{org}/dashboards/{id})
curl -s -u "root@example.com:Q1w2E3r4!" http://localhost:5080/api/default/dashboards/7517438982746013696
实测回显(节选):
{"v1":null,"v2":null,"v3":null,"v4":null,"v5":null,"v6":null,"v7":null,"v8":{"version":8,"dashboardId":"7517438982746013696","title":"api-demo-dash","description":"created by API doc test","role":"",
更新要点:更新(PUT)时请求体必须回传 GET 返回的完整信封(含 hash 字段做并发冲突检测),只传业务字段会被拒绝。
7.3 删除(DELETE /api/{org}/dashboards/{id})
curl -s -u "root@example.com:Q1w2E3r4!" -X DELETE http://localhost:5080/api/default/dashboards/7517438982746013696
实测回显:
{"code":200,"message":"Dashboard deleted"}
八、告警 API(v2)
v1.1.1 的告警 API 为 v2 版本(/api/{org}/v2/alerts),依赖两块基础资源:模板(Template)与目的地(Destination)。
8.1 模板与目的地(/api/{org}/alerts/templates、/api/{org}/alerts/destinations)
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST http://localhost:5080/api/default/alerts/templates \
-H "Content-Type: application/json" \
-d '{"name":"webhook-tpl","body":"Alert {alert_name} on {stream_name}: {alert_body}"}'
实测回显:
{"code":200,"message":"Template saved"}
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST http://localhost:5080/api/default/alerts/destinations \
-H "Content-Type: application/json" \
-d '{"name":"httpbin-hook","url":"https://httpbin.org/post","method":"post","headers":{},"template_name":"webhook-tpl","skip_tls_verify":false}'
实测回显:
{"code":200,"message":"Destination saved","id":"3KqtwuyLrMqSiIX2WPRZEktHpHm","name":"httpbin-hook"}
安全防护实录(SSRF guard):目的地 URL 指向私网地址时被服务端拒绝,实测回显:
{"code":400,"message":"Destination URL blocked by SSRF guard: Access to private IP address 127.0.0.1 is not allowed for security reasons. This prevents Server-Side Request Forgery (SSRF) attacks."}
这说明 v1.1.1 对 webhook 目的地内建了 SSRF 防护(拒绝 127.0.0.1/私网/链路本地地址),设计上避免了恶意告警目的地穿透内网。
8.2 创建告警(POST /api/{org}/v2/alerts)
cat > /tmp/alert.json << 'EOF'
{"name":"app_error_alert","stream_name":"app_logs","stream_type":"logs","is_real_time":false,
"query_condition":{"type":"sql","conditions":[],
"sql":"SELECT count(*) AS err_count FROM app_logs WHERE level = 'error'",
"multi_time_range":[]},
"trigger_condition":{"period":1,"operator":">=","threshold":1,
"frequency":1,"frequency_type":"minutes","cron":"","silence":10},
"destinations":["httpbin-hook"],
"description":"Alert when error log appears in app_logs",
"enabled":true,"context_attributes":{}}
EOF
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST http://localhost:5080/api/v2/default/alerts \
-H "Content-Type: application/json" \
--data-binary @/tmp/alert.json
实测回显:
{"code":200,"message":"Alert saved","id":"3KqtwsOBziuO1yogWwnvVfW8nTk","name":"app_error_alert"}
请求体关键字段:
| 字段 | 说明 |
|---|---|
query_condition.sql | 调度器周期执行的 SQL,type: sql |
trigger_condition.period / threshold / operator | 统计窗口(分钟)+ 触发阈值比较 |
trigger_condition.frequency / frequency_type | 调度频率(分钟/小时/cron) |
trigger_condition.silence | 触发后的静默期(分钟),防告警风暴 |
destinations | 目的地名称字符串数组(v2 契约) |
依赖校验实录:destinations 引用不存在的目的地时创建被拒(实测删除目的地后再创建即复现):
{"code":404,"message":"Alert destination httpbin-hook not found"}
8.3 列表 / 详情 / 删除
curl -s -u "root@example.com:Q1w2E3r4!" http://localhost:5080/api/v2/default/alerts
实测回显(节选):
{"list":[{"alert_id":"3KqtwsOBziuO1yogWwnvVfW8nTk","folder_id":"default","folder_name":"default","name":"app_error_alert","owner":"root@example.com","description":"Alert when error log appears in app_logs","alert_type":"scheduled","stream_name":"app_logs","stream_type":"logs","condition":{"type":"sql","conditions":{"and":[]},"sql":"SELECT count(*) AS err_count FROM app_logs WHERE level = 'error'",...},"trigger_condition":{"period":1,"operator":">=","threshold":1,"frequency":1,...
注意列表项主键字段是 alert_id(创建响应里叫 id)。详情与删除:
curl -s -u "root@example.com:Q1w2E3r4!" http://localhost:5080/api/v2/default/alerts/3KqtwsOBziuO1yogWwnvVfW8nTk # GET 详情
curl -s -u "root@example.com:Q1w2E3r4!" -X DELETE http://localhost:5080/api/v2/default/alerts/3KqtwsOBziuO1yogWwnvVfW8nTk
删除实测回显:
{"code":200,"message":"Alert deleted"}
九、用户与函数 API
9.1 用户管理(/api/{org}/users)
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST http://localhost:5080/api/default/users \
-H "Content-Type: application/json" \
-d '{"email":"apitest@example.com","password":"Q1w2E3r4!","role":"admin","first_name":"API","last_name":"Test"}'
实测回显:
{"code":200,"message":"User saved successfully"}
角色取值实录:role 仅接受内置角色(admin/member/viewer/root)。实测传 viewer/member 以外的自定义角色名会报 "Custom roles not allowed" 类错误;开源版自建用户用 admin 或 member。用户列表:
curl -s -u "root@example.com:Q1w2E3r4!" http://localhost:5080/api/default/users
实测回显(节选):
{"data":[{"email":"apitest@example.com","first_name":"API","last_name":"Test","role":"admin","is_external":false,"created_at":1792297140708570},{...},{"email":"root@example.com","first_name":"root","last_name":"","role":"root","is_external":false,"created_at":179226...
删除(从当前组织移除):
curl -s -u "root@example.com:Q1w2E3r4!" -X DELETE http://localhost:5080/api/default/users/apitest@example.com
实测回显:
{"code":200,"message":"User removed from organization"}
9.2 查询函数(/api/{org}/functions)
函数是 VRL(Vector Remap Language)脚本,摄入/查询时做行级数据加工:
curl -s -u "root@example.com:Q1w2E3r4!" \
-X POST http://localhost:5080/api/default/functions \
-H "Content-Type: application/json" \
-d '{"name":"drop_debug","function":"if .level == \"debug\" { \"\" } else { . }","params":""}'
实测回显:
{"code":200,"message":"Function saved successfully"}
curl -s -u "root@example.com:Q1w2E3r4!" http://localhost:5080/api/default/functions
实测回显:
{"list":[{"function":"if .level == \"debug\" { \"\" } else { . } \n .","name":"drop_debug","params":"","numArgs":0,"transType":0}]}
curl -s -u "root@example.com:Q1w2E3r4!" -X DELETE http://localhost:5080/api/default/functions/drop_debug
实测回显:
{"code":200,"message":"Function deleted"}
十、错误处理与通用约定
状态码语义(实测归纳):
| 状态码 | 典型场景 | 响应形态 |
|---|---|---|
| 200 | 成功 | 业务对象或 {"code":200,"message":"..."} |
| 400 | 请求体不合法 / 业务规则拒绝 | {"code":400,"message":"Error# ..."}(如 _multi 非 JSON) |
| 401 | 缺失/错误凭据 | 空 body + HTTP/1.1 401 Unauthorized |
| 404 | 资源不存在 / 引用依赖缺失 | {"code":404,"message":"... not found"} |
通用约定:
- 时间参数一律微秒时间戳(
start_time/end_time/_timestamp;秒 ×1,000,000); - 流(Stream)无需预建,首次写入自动创建并推断 schema;字段名大小写敏感;
- 组织路径
/api/default/中的default为 org_id,多组织部署替换为对应组织标识; - 删除类 API 语义直接(stream/dashboard/alert 等删除即生效),生产集成建议先查后删;
- 告警 v2 的
destinations是字符串数组,且目的地必须已存在(404 强校验); x-api-node响应头可识别处理节点,集群排障时配合日志使用。