openobserve-cli 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/PKG-INFO +19 -1
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/README.md +18 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/pyproject.toml +9 -1
- openobserve_cli-0.2.0/skills/openobserve/SKILL.md +145 -0
- openobserve_cli-0.2.0/skills/openobserve/references/admin.md +126 -0
- openobserve_cli-0.2.0/skills/openobserve/references/alerts.md +184 -0
- openobserve_cli-0.2.0/skills/openobserve/references/cli.md +148 -0
- openobserve_cli-0.2.0/skills/openobserve/references/dashboards.md +155 -0
- openobserve_cli-0.2.0/skills/openobserve/references/endpoints.md +693 -0
- openobserve_cli-0.2.0/skills/openobserve/references/metrics.md +72 -0
- openobserve_cli-0.2.0/skills/openobserve/references/pipelines.md +119 -0
- openobserve_cli-0.2.0/skills/openobserve/references/search.md +162 -0
- openobserve_cli-0.2.0/skills/openobserve/references/streams.md +137 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/src/oo_cli/__init__.py +1 -1
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/src/oo_cli/cli.py +36 -0
- openobserve_cli-0.2.0/src/oo_cli/skill.py +54 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/src/oo_cli/spec.py +16 -8
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/tests/test_cli.py +11 -1
- openobserve_cli-0.2.0/tests/test_skill.py +41 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/tests/test_spec.py +8 -0
- openobserve_cli-0.1.0/.github/workflows/publish.yaml +0 -36
- openobserve_cli-0.1.0/.github/workflows/test.yaml +0 -45
- openobserve_cli-0.1.0/.pre-commit-config.yaml +0 -39
- openobserve_cli-0.1.0/uv.lock +0 -453
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/.gitignore +0 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/LICENSE +0 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/src/oo_cli/__main__.py +0 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/src/oo_cli/client.py +0 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/src/oo_cli/config.py +0 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/src/oo_cli/py.typed +0 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/src/oo_cli/timeutil.py +0 -0
- {openobserve_cli-0.1.0 → openobserve_cli-0.2.0}/tests/test_client.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: openobserve-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: CLI for the OpenObserve HTTP API
|
|
5
5
|
Project-URL: Homepage, https://github.com/paveldedik/oo-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/paveldedik/oo-cli
|
|
@@ -111,6 +111,24 @@ oo spec refresh # refetch after an OpenObserve upgrade
|
|
|
111
111
|
Without a reachable spec the CLI falls back to v1, except for `alerts`, `folders` and
|
|
112
112
|
`reports`, the three resources that have a v2 in OpenObserve 0.91.
|
|
113
113
|
|
|
114
|
+
## Skill for agents
|
|
115
|
+
|
|
116
|
+
The CLI carries a skill for coding agents: how the commands map onto the API, what the
|
|
117
|
+
bodies look like, and a reference for every endpoint, written from an instance's own
|
|
118
|
+
OpenAPI document. It installs itself.
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
oo skill install # -> ~/.claude/skills/openobserve
|
|
122
|
+
oo skill update # after upgrading the CLI
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`--dir` puts it somewhere else (`oo skill install --dir .claude/skills` for one project),
|
|
126
|
+
`--force` overwrites an existing copy, and `oo skill path` prints the bundled original.
|
|
127
|
+
Without installing anything: `uvx openobserve-cli skill install`.
|
|
128
|
+
|
|
129
|
+
The files are also plain Markdown in `skills/openobserve`, so any agent that reads
|
|
130
|
+
Markdown can be pointed straight at `SKILL.md`.
|
|
131
|
+
|
|
114
132
|
## Development
|
|
115
133
|
|
|
116
134
|
```bash
|
|
@@ -88,6 +88,24 @@ oo spec refresh # refetch after an OpenObserve upgrade
|
|
|
88
88
|
Without a reachable spec the CLI falls back to v1, except for `alerts`, `folders` and
|
|
89
89
|
`reports`, the three resources that have a v2 in OpenObserve 0.91.
|
|
90
90
|
|
|
91
|
+
## Skill for agents
|
|
92
|
+
|
|
93
|
+
The CLI carries a skill for coding agents: how the commands map onto the API, what the
|
|
94
|
+
bodies look like, and a reference for every endpoint, written from an instance's own
|
|
95
|
+
OpenAPI document. It installs itself.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
oo skill install # -> ~/.claude/skills/openobserve
|
|
99
|
+
oo skill update # after upgrading the CLI
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`--dir` puts it somewhere else (`oo skill install --dir .claude/skills` for one project),
|
|
103
|
+
`--force` overwrites an existing copy, and `oo skill path` prints the bundled original.
|
|
104
|
+
Without installing anything: `uvx openobserve-cli skill install`.
|
|
105
|
+
|
|
106
|
+
The files are also plain Markdown in `skills/openobserve`, so any agent that reads
|
|
107
|
+
Markdown can be pointed straight at `SKILL.md`.
|
|
108
|
+
|
|
91
109
|
## Development
|
|
92
110
|
|
|
93
111
|
```bash
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
# "oo", "oo-cli" and "openobserve" are all taken on PyPI.
|
|
3
3
|
name = "openobserve-cli"
|
|
4
|
-
version = "0.
|
|
4
|
+
version = "0.2.0"
|
|
5
5
|
description = "CLI for the OpenObserve HTTP API"
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
keywords = ["openobserve", "observability", "logs", "metrics", "traces", "cli"]
|
|
@@ -42,6 +42,14 @@ dev = ["pytest>=8", "mypy>=1.18", "ruff>=0.14"]
|
|
|
42
42
|
[tool.hatch.build.targets.wheel]
|
|
43
43
|
packages = ["src/oo_cli"]
|
|
44
44
|
|
|
45
|
+
# The agent skill lives at the top of the repository, where agents browsing GitHub find
|
|
46
|
+
# it, and rides along in the package so `oo skill install` needs no checkout.
|
|
47
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
48
|
+
"skills/openobserve" = "oo_cli/_skill"
|
|
49
|
+
|
|
50
|
+
[tool.hatch.build.targets.sdist]
|
|
51
|
+
include = ["src", "skills", "tests", "README.md", "LICENSE", "pyproject.toml"]
|
|
52
|
+
|
|
45
53
|
[tool.ruff]
|
|
46
54
|
line-length = 100
|
|
47
55
|
target-version = "py311"
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: openobserve
|
|
3
|
+
description: Query and manage OpenObserve from a terminal with the `oo` CLI - search logs, traces and metrics with SQL or PromQL, and read or change streams, dashboards, alerts, pipelines, functions and reports. Use for any task that mentions OpenObserve, an `oo` command, or an OpenObserve API path.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# OpenObserve from the command line
|
|
8
|
+
|
|
9
|
+
`oo` is a transcription of the OpenObserve HTTP API, not a model of it. One rule covers
|
|
10
|
+
almost everything:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
oo <method> <resource> -> <METHOD> /api/{org}/<resource>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
So `oo get dashboards` is `GET /api/default/dashboards`, and `oo delete alerts/7` is
|
|
17
|
+
`DELETE /api/v2/default/alerts/7`. Where an endpoint exists in two versions the CLI picks
|
|
18
|
+
v2; there is no version flag. Anything the rule does not reach is still one command away
|
|
19
|
+
with `oo api <METHOD> <path>`.
|
|
20
|
+
|
|
21
|
+
Install with `uv tool install openobserve-cli`, or run it without installing:
|
|
22
|
+
`uvx openobserve-cli get streams`. This skill came from that package - `oo skill update`
|
|
23
|
+
refreshes it after the CLI is upgraded.
|
|
24
|
+
|
|
25
|
+
## Start here
|
|
26
|
+
|
|
27
|
+
Check what you are pointed at before anything else - it is the difference between an empty
|
|
28
|
+
result and an empty instance:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
oo api GET /healthz # {"status":"ok"} - confirms it is an OpenObserve
|
|
32
|
+
oo get organizations # confirms the credentials and lists the orgs you can use
|
|
33
|
+
oo get streams # what data this org actually holds
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Configuration is environment only:
|
|
37
|
+
|
|
38
|
+
| Variable | Required | Default |
|
|
39
|
+
|---------------------------|-----------------------------------|-------------------------|
|
|
40
|
+
| `OO_ENDPOINT` | optional | `http://localhost:5080` |
|
|
41
|
+
| `OO_ORG` | optional | `default` |
|
|
42
|
+
| `OO_TOKEN` | to reach anything but `/healthz` | - |
|
|
43
|
+
| `OO_USER` / `OO_PASSWORD` | instead of `OO_TOKEN` | - |
|
|
44
|
+
| `OO_COOKIE` | when a gateway guards the host | - |
|
|
45
|
+
| `OO_TIMEOUT` | optional | `60` (seconds) |
|
|
46
|
+
|
|
47
|
+
`--endpoint`, `--org` and `--timeout` override the variables per command. Never print a
|
|
48
|
+
token or cookie value back to the user; keep it in the environment.
|
|
49
|
+
|
|
50
|
+
## The grammar
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
oo get alerts --folder default # unknown --flags become query parameters
|
|
54
|
+
oo get streams/app_logs/schema # slashes are path segments
|
|
55
|
+
oo post alerts -f alert.json # -f file, -d '<literal>', -d @file, -d @-
|
|
56
|
+
oo put alerts/7 -d @- < alert.json # body on stdin
|
|
57
|
+
oo --org other get streams # global flags go before the verb
|
|
58
|
+
oo search --sql "select * from k8s_logs limit 10" --from -15m
|
|
59
|
+
oo api GET /api/default/prometheus/api/v1/query --query "up"
|
|
60
|
+
oo spec paths alerts # what this instance actually serves
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- Output is pretty-printed JSON on stdout; errors on stderr. Pipe into `jq`.
|
|
64
|
+
- Exit code 1 on HTTP >= 400 (the response body is printed), 2 on a bad command.
|
|
65
|
+
- `--raw` prints the body unformatted, for CSV or a large export.
|
|
66
|
+
- Values starting with `-` need `--flag=value`; `--from` and `--to` are handled for you.
|
|
67
|
+
|
|
68
|
+
## Time
|
|
69
|
+
|
|
70
|
+
Every timestamp the API takes or returns is **epoch microseconds**. `oo search --from/--to`
|
|
71
|
+
and nothing else accepts friendly forms: `now`, an offset (`-15m`, `-2h`, `-7d`), an epoch
|
|
72
|
+
in seconds/milliseconds/microseconds, or ISO 8601 (local time when it carries no zone).
|
|
73
|
+
Elsewhere - `start_time` in a body, `_values`, alert history - pass microseconds:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
python3 -c 'import time; print(int(time.time()*1_000_000))'
|
|
77
|
+
date -v-1H +%s000000 # macOS (GNU: date -d '1 hour ago' +%s000000)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Searching
|
|
81
|
+
|
|
82
|
+
`oo search` is the one command that is not a straight transcription: it wraps
|
|
83
|
+
`POST /api/{org}/_search` so the body does not have to be written by hand.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
oo search --sql "select * from k8s_logs where level = 'error'" --from -1h --size 50
|
|
87
|
+
oo search --sql "select k8s_namespace_name, count(*) as n from k8s_logs
|
|
88
|
+
group by k8s_namespace_name order by n desc" --from -6h
|
|
89
|
+
oo search --type metrics --sql "select * from up" --from -5m
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`--from` defaults to `-1h`, `--to` to `now`, `--size` to 100, `--type` to `logs`. The SQL is
|
|
93
|
+
DataFusion SQL: the stream is the table, `_timestamp` is microseconds, and full text lives in
|
|
94
|
+
`match_all('needle')`. Read `references/search.md` before writing anything more involved -
|
|
95
|
+
histograms, `_values`, `_around`, async search jobs and the raw `_search` body are all there.
|
|
96
|
+
|
|
97
|
+
Two habits that keep a search cheap on a busy instance: always bound the time range, and
|
|
98
|
+
aggregate in SQL rather than pulling rows and counting them locally. A wide range over a raw
|
|
99
|
+
stream can cost the instance far more memory than it costs you to type.
|
|
100
|
+
|
|
101
|
+
## Common tasks
|
|
102
|
+
|
|
103
|
+
| Question | Command |
|
|
104
|
+
|----------|---------|
|
|
105
|
+
| what is in this instance | `oo get streams`, then `oo get streams/<name>/schema` |
|
|
106
|
+
| errors in the last hour | `oo search --sql "select * from <stream> where level = 'error'" --from -1h` |
|
|
107
|
+
| how many, by service | `oo search --sql "select service, count(*) as n from <stream> group by service order by n desc" --from -6h` |
|
|
108
|
+
| which values does this field take | `oo get <stream>/_values --fields <field> --size 20 --start_time <us> --end_time <us>` |
|
|
109
|
+
| current value of a metric | `oo api GET /api/{org}/prometheus/api/v1/query --query '<promql>'` |
|
|
110
|
+
| which alerts exist, and are they on | `oo get alerts \| jq -r '.list[] \| "\(.enabled) \(.name)"'` |
|
|
111
|
+
| why an alert did not fire | `oo get alerts/history --alert_id <id> --start_time <us> --end_time <us>` |
|
|
112
|
+
| back up a dashboard | `oo get dashboards/<id> --folder <folder> > dashboard.json` |
|
|
113
|
+
| change one field of an object | read it, edit the JSON, `oo put <resource>/<id> -f patched.json` |
|
|
114
|
+
| does this instance have X | `oo spec paths <needle>` |
|
|
115
|
+
|
|
116
|
+
## Rules worth keeping
|
|
117
|
+
|
|
118
|
+
1. **Read before you write.** `PUT` replaces the whole object. Fetch it, edit that JSON,
|
|
119
|
+
send it back - never hand-write a replacement from the docs.
|
|
120
|
+
2. **Dashboards need their `hash`.** `PUT dashboards/<id>` takes `?folder=<id>&hash=<hash>`
|
|
121
|
+
from the object you just read; without it a concurrent edit is silently overwritten.
|
|
122
|
+
3. **Folders are ids, not names.** `--folder default` is the id of the default folder;
|
|
123
|
+
any other folder is a ksuid you get from `oo get folders/<dashboards|alerts|reports>`.
|
|
124
|
+
4. **Deletes are permanent** and `oo delete streams/<name> --delete_all=true` takes the
|
|
125
|
+
alerts and dashboards with it. Confirm with the user before any delete.
|
|
126
|
+
5. **Ask the spec, not your memory.** `oo spec paths <needle>` lists what the connected
|
|
127
|
+
instance serves; `oo spec refresh` refetches it after an upgrade. Endpoint availability
|
|
128
|
+
differs between OSS and enterprise builds - several alert and cipher endpoints answer
|
|
129
|
+
"not supported" on OSS.
|
|
130
|
+
6. When a command says a path *is not in the spec*, the resource name is probably wrong -
|
|
131
|
+
check with `oo spec paths` instead of retrying variations.
|
|
132
|
+
|
|
133
|
+
## References
|
|
134
|
+
|
|
135
|
+
| File | What is in it |
|
|
136
|
+
|------|---------------|
|
|
137
|
+
| `references/cli.md` | Full command grammar, v1/v2 resolution, the spec cache, gateways, error messages |
|
|
138
|
+
| `references/search.md` | `_search` body, SQL dialect, histograms, `_values`, `_around`, search jobs, patterns |
|
|
139
|
+
| `references/metrics.md` | PromQL instant/range queries, labels, series, metadata, metric ingestion |
|
|
140
|
+
| `references/alerts.md` | Alert model (v2), trigger and query conditions, destinations, templates, history, incidents |
|
|
141
|
+
| `references/dashboards.md` | Dashboards, panels, annotations, folders, scheduled reports |
|
|
142
|
+
| `references/streams.md` | Streams, schemas, settings, retention, ingestion endpoints, enrichment tables |
|
|
143
|
+
| `references/pipelines.md` | Pipelines (nodes and edges), VRL functions, actions |
|
|
144
|
+
| `references/admin.md` | Organizations, settings, users, roles, groups, service accounts, tokens, KV |
|
|
145
|
+
| `references/endpoints.md` | Every endpoint the API exposes, as the `oo` command that reaches it |
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Organizations, users and the rest
|
|
2
|
+
|
|
3
|
+
## Organizations
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
oo get organizations # /api/organizations - no org in the path
|
|
7
|
+
oo post organizations -d '{"name":"team-b"}'
|
|
8
|
+
oo put rename -d '{"new_name":"Platform"}'
|
|
9
|
+
oo get summary # ingestion, storage, stream and function counts
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`oo get organizations` is the first call to make against an unfamiliar instance: it proves
|
|
13
|
+
the credential works and lists the org identifiers `--org` accepts. A root user sees every
|
|
14
|
+
organization. `oo get clusters` lists clusters in a distributed deployment.
|
|
15
|
+
|
|
16
|
+
## Ingestion tokens
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
oo get passcode # the current ingestion token for this user and org
|
|
20
|
+
oo put passcode # rotate it - every ingester using the old one breaks
|
|
21
|
+
oo get rumtoken
|
|
22
|
+
oo post rumtoken # create the first RUM token
|
|
23
|
+
oo put rumtoken # rotate it
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
These return credentials. Never print one into a chat, a commit or a log; redirect to a file
|
|
27
|
+
or into an environment variable.
|
|
28
|
+
|
|
29
|
+
## Settings
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
oo get settings
|
|
33
|
+
oo post settings -d '{"scrape_interval": 15}'
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Org settings hold `scrape_interval`, `trace_id_field_name` / `span_id_field_name`,
|
|
37
|
+
`max_series_per_query`, `min_auto_refresh_interval`, `toggle_ingestion_logs`,
|
|
38
|
+
`usage_stream_enabled`, `enable_streaming_search`, `streaming_aggregation_enabled`, the two
|
|
39
|
+
theme colours and `cross_links`.
|
|
40
|
+
|
|
41
|
+
A newer key-value system sits alongside it, resolving system -> org -> user:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
oo get settings/v2 # everything, resolved
|
|
45
|
+
oo get settings/v2 --category ui
|
|
46
|
+
oo get settings/v2/<key> --user_id <id> # the value this user actually sees
|
|
47
|
+
oo post settings/v2 -d '{"setting_key":"...","setting_value":...,"setting_category":"ui"}'
|
|
48
|
+
oo post settings/v2/user/<user_id> -d '{"setting_key":"...","setting_value":...}'
|
|
49
|
+
oo delete settings/v2/<key> # falls back to the system default
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Users, roles, groups, service accounts
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
oo get users
|
|
56
|
+
oo post users -d '{"email":"a@example.com","password":"...","role":"admin","first_name":"A","last_name":"B"}'
|
|
57
|
+
oo put users/<email> -d '{"first_name":"A"}'
|
|
58
|
+
oo post users/<email> -d '{"role":"member"}' # add an existing user to this org
|
|
59
|
+
oo delete users/<email> # removes from the org
|
|
60
|
+
|
|
61
|
+
oo get roles # enterprise RBAC
|
|
62
|
+
oo get roles/<role_id>/permissions/<resource>
|
|
63
|
+
oo get roles/<role_id>/users
|
|
64
|
+
oo post roles -d '{"role":"readonly"}'
|
|
65
|
+
oo put roles/<role_id> -f permissions.json
|
|
66
|
+
|
|
67
|
+
oo get groups
|
|
68
|
+
oo post groups -d '{"name":"platform"}'
|
|
69
|
+
oo put groups/<group_name> -d '{"add_users":["a@example.com"],"add_roles":["readonly"]}'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
A service account is a user without a password, used for automation; its token comes from
|
|
73
|
+
`passcode` once the account exists.
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
oo get service_accounts
|
|
77
|
+
oo post service_accounts -d '{"email":"ci@example.com","first_name":"CI","last_name":"bot"}'
|
|
78
|
+
oo delete service_accounts/<email>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Roles and groups are enterprise features and answer with an error on OSS builds. Creating or
|
|
82
|
+
deleting users changes who can reach the data - always confirm first.
|
|
83
|
+
|
|
84
|
+
## Key-value store
|
|
85
|
+
|
|
86
|
+
A small per-org store the UI uses and you can too:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
oo get kv # every key
|
|
90
|
+
oo get kv --prefix dashboard_
|
|
91
|
+
oo get kv/<key> # the raw value, not JSON
|
|
92
|
+
oo post kv/<key> -d 'some text'
|
|
93
|
+
oo delete kv/<key>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Short URLs
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
oo post short -d '{"original_url":"https://openobserve.example.com/web/logs?..."}'
|
|
100
|
+
oo api GET /short/default/short/<short_id> --type ui # resolve without redirecting
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Cipher keys and rate limits
|
|
104
|
+
|
|
105
|
+
`cipher_keys` (encryption key management) and `ratelimit` (per-module and per-role request
|
|
106
|
+
limits) are enterprise-only:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
oo get cipher_keys
|
|
110
|
+
oo get ratelimit/module_list --org_id default
|
|
111
|
+
oo get ratelimit/role_list --org_id default --user_role admin
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Health and the spec
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
oo api GET /healthz # {"status":"ok"}, the one endpoint needing no credential
|
|
118
|
+
oo spec paths # every path this build serves
|
|
119
|
+
oo spec refresh # after an upgrade
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## MCP
|
|
123
|
+
|
|
124
|
+
Recent builds expose `POST /api/{org}/mcp`, an MCP server over the same API. The endpoint
|
|
125
|
+
carries per-operation hints (which operations are exposed, which need confirmation) that this
|
|
126
|
+
skill's guidance is drawn from. Check `oo spec paths mcp` before assuming it is there.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Alerts, destinations and templates
|
|
2
|
+
|
|
3
|
+
Three objects, in the order you need them:
|
|
4
|
+
|
|
5
|
+
1. a **template** formats the message,
|
|
6
|
+
2. a **destination** says where it goes and which template it uses,
|
|
7
|
+
3. an **alert** says what to watch and names its destinations.
|
|
8
|
+
|
|
9
|
+
Alerts live in folders and use the v2 API, so `oo get alerts` is
|
|
10
|
+
`GET /api/v2/{org}/alerts`. Destinations and templates are v1.
|
|
11
|
+
|
|
12
|
+
## Listing
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
oo get alerts # every alert in the org
|
|
16
|
+
oo get alerts --folder default --enabled true
|
|
17
|
+
oo get alerts --alert_name_substring celery --alert_type scheduled
|
|
18
|
+
oo get alerts --stream_type logs --stream_name k8s_logs
|
|
19
|
+
oo get alerts --page_size 50 --page_idx 1
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Filters: `folder` (a folder **id**), `stream_type`, `stream_name` (only with
|
|
23
|
+
`stream_type`), `alert_name_substring` (case-insensitive), `owner`, `enabled`,
|
|
24
|
+
`alert_type` (`all`, `scheduled`, `realtime`, `anomaly_detection`), `page_size`, `page_idx`.
|
|
25
|
+
|
|
26
|
+
Each item carries `alert_id`, `name`, `enabled`, `folder_id`, `folder_name`,
|
|
27
|
+
`is_real_time`, `last_triggered_at` and `last_satisfied_at`.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
oo get alerts | jq -r '.list[] | select(.enabled) | "\(.folder_name)/\(.name)"'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## One alert
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
oo get alerts/<alert_id> # add --folder <id> for a non-default folder
|
|
37
|
+
oo post alerts/<alert_id>/export # the same thing, shaped for re-import
|
|
38
|
+
oo patch alerts/<alert_id>/enable --value=false
|
|
39
|
+
oo patch alerts/<alert_id>/trigger # fire it now, to test the destination
|
|
40
|
+
oo post alerts/<alert_id>/clone -d '{"name": "copy_of_x", "folder_id": "<id>"}'
|
|
41
|
+
oo patch alerts/move -d '{"alert_ids": ["<id>"], "dst_folder_id": "<id>"}'
|
|
42
|
+
oo delete alerts/<alert_id> # permanent
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## The alert object
|
|
46
|
+
|
|
47
|
+
Names must be snake_case: no spaces and none of `: # ? & % /` or quotes. `destinations` is
|
|
48
|
+
required and every name in it must already exist.
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"name": "api_error_rate",
|
|
53
|
+
"stream_type": "logs",
|
|
54
|
+
"stream_name": "k8s_logs",
|
|
55
|
+
"is_real_time": false,
|
|
56
|
+
"enabled": true,
|
|
57
|
+
"description": "5xx from the API gateway",
|
|
58
|
+
"destinations": ["slack_alerts"],
|
|
59
|
+
"query_condition": {
|
|
60
|
+
"type": "sql",
|
|
61
|
+
"sql": "select count(*) as n from k8s_logs where status >= 500"
|
|
62
|
+
},
|
|
63
|
+
"trigger_condition": {
|
|
64
|
+
"period": 10, "frequency": 600, "operator": ">=", "threshold": 5, "silence": 30
|
|
65
|
+
},
|
|
66
|
+
"context_attributes": {"team": "platform"},
|
|
67
|
+
"row_template": "{alert_name} fired: {n}"
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### `trigger_condition` - when it runs and what counts as firing
|
|
72
|
+
|
|
73
|
+
| Field | Unit | Meaning |
|
|
74
|
+
|-------|------|---------|
|
|
75
|
+
| `period` | minutes | how far back each evaluation looks |
|
|
76
|
+
| `frequency` | seconds | how often it evaluates (`frequency_type: "minutes"`) |
|
|
77
|
+
| `frequency_type` | - | `minutes` or `cron` |
|
|
78
|
+
| `cron` | - | schedule when `frequency_type` is `cron` |
|
|
79
|
+
| `timezone` | - | timezone for the cron expression |
|
|
80
|
+
| `operator` | - | `=`, `!=`, `>`, `>=`, `<`, `<=`, `contains`, `not_contains` |
|
|
81
|
+
| `threshold` | - | compared against the row count or the aggregate |
|
|
82
|
+
| `silence` | minutes | mute after firing, so one incident is one notification |
|
|
83
|
+
| `align_time` | - | snap evaluations to the clock |
|
|
84
|
+
| `tolerance_in_secs` | seconds | slack for late-arriving data |
|
|
85
|
+
|
|
86
|
+
`period` shorter than the data's ingestion delay is the usual reason an alert never fires.
|
|
87
|
+
|
|
88
|
+
### `query_condition` - what it asks
|
|
89
|
+
|
|
90
|
+
`type` is one of three, and the other fields follow from it:
|
|
91
|
+
|
|
92
|
+
- **`custom`** - `conditions` (a condition group), optional `aggregation`, `vrl_function`,
|
|
93
|
+
`multi_time_range`. The UI builds this one.
|
|
94
|
+
- **`sql`** - `sql` plus optional `vrl_function`. The query must return rows only when
|
|
95
|
+
something is wrong, or return a number that `trigger_condition` compares.
|
|
96
|
+
- **`promql`** - `promql` plus `promql_condition` (`{"column", "operator", "value"}`), for
|
|
97
|
+
alerts on metrics.
|
|
98
|
+
|
|
99
|
+
`aggregation` narrows a custom alert: `function` is one of `avg`, `min`, `max`, `sum`,
|
|
100
|
+
`count`, `median`, `p50`, `p75`, `p90`, `p95`, `p99`, with `group_by` and a `having` clause
|
|
101
|
+
shaped `{"column", "operator", "value", "ignore_case"}`.
|
|
102
|
+
|
|
103
|
+
`POST /api/v2/{org}/alerts/generate_sql` turns a custom condition into the SQL it would run -
|
|
104
|
+
useful for checking an alert before saving it.
|
|
105
|
+
|
|
106
|
+
The `conditions` group is the same nested format pipelines use (see `pipelines.md`):
|
|
107
|
+
`{"filterType": "group", "logicalOperator": "AND", "conditions": [...]}` with leaves
|
|
108
|
+
`{"filterType": "condition", "column", "operator", "value", "logicalOperator"}`. When in
|
|
109
|
+
doubt, build one alert in the UI, `oo get alerts/<id>`, and copy the shape.
|
|
110
|
+
|
|
111
|
+
### Editing an existing alert
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
oo get alerts/<id> > alert.json
|
|
115
|
+
jq '.trigger_condition.threshold = 10' alert.json > patched.json
|
|
116
|
+
oo put alerts/<id> -f patched.json
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`PUT` replaces the object, so always start from the current one.
|
|
120
|
+
|
|
121
|
+
## Destinations
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
oo get alerts/destinations
|
|
125
|
+
oo get alerts/destinations --module pipeline # pipeline destinations instead
|
|
126
|
+
oo get alerts/destinations/<name>
|
|
127
|
+
oo post alerts/destinations -d '{"name":"slack_alerts","type":"http","url":"https://hooks.example.com/x","method":"post","template":"Default"}'
|
|
128
|
+
oo post alerts/destinations -d '{"name":"oncall_mail","type":"email","emails":["oncall@example.com"],"template":"Default"}'
|
|
129
|
+
oo delete alerts/destinations/<name>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`template` is **required** for an alert destination - without it the destination is created
|
|
133
|
+
as a pipeline destination and no alert can use it. `type` is `http`, `email` or `sns`
|
|
134
|
+
(`sns_topic_arn` + `aws_region`). `headers` adds HTTP headers, `skip_tls_verify` disables
|
|
135
|
+
certificate checks. A destination in use cannot be deleted.
|
|
136
|
+
|
|
137
|
+
## Templates
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
oo get alerts/templates
|
|
141
|
+
oo get alerts/templates/system/prebuilt # read-only, Slack/Teams/PagerDuty/...
|
|
142
|
+
oo get alerts/templates/<name>
|
|
143
|
+
oo post alerts/templates -d '{"name":"short","type":"http","body":"{\"text\":\"{alert_name} fired\"}"}'
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`body` is the message with `{variable}` placeholders; `title` is used for email. Variables
|
|
147
|
+
come from the alert (`alert_name`, `stream_name`, `org_name`, `alert_start_time`, ...),
|
|
148
|
+
its `context_attributes`, and the matching rows via `row_template`. Templates named
|
|
149
|
+
`system_*` are prebuilt and read-only.
|
|
150
|
+
|
|
151
|
+
## History and incidents
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
oo get alerts/history --alert_id <id> --start_time <us> --end_time <us> --size 100
|
|
155
|
+
oo get alerts/history --sort_by timestamp --sort_order desc
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
History comes from the org's own triggers stream: when an alert ran, whether it was
|
|
159
|
+
satisfied, whether it was silenced, how long the evaluation took, and any error. It is the
|
|
160
|
+
first place to look when someone says an alert did not fire.
|
|
161
|
+
|
|
162
|
+
Incidents group notifications for alerts with `creates_incident: true`:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
oo get alerts/incidents --status open --limit 20 # open, acknowledged or resolved
|
|
166
|
+
oo get alerts/incidents/stats
|
|
167
|
+
oo get alerts/incidents/<incident_id>
|
|
168
|
+
oo patch alerts/incidents/<incident_id>/update -d '{"status":"resolved"}' # one field per call
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Deduplication (`alerts/deduplication/...`) and RCA are enterprise features; on OSS they
|
|
172
|
+
answer "not supported".
|
|
173
|
+
|
|
174
|
+
## Folders
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
oo get folders/alerts # folder_type is dashboards, alerts or reports
|
|
178
|
+
oo get folders/alerts/name/<folder_name>
|
|
179
|
+
oo post folders/alerts -d '{"name":"platform","description":"team alerts"}'
|
|
180
|
+
oo delete folders/alerts/<folder_id>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`--folder` everywhere takes the **folderId**, not the name. The default folder's id is
|
|
184
|
+
literally `default`.
|