233 lines
No EOL
8.2 KiB
Markdown
233 lines
No EOL
8.2 KiB
Markdown
# OpenAI-compatible Usage – Grafana Query Guide
|
||
|
||
> **Purpose**: 이 문서는 운영자가 Prometheus metric을 Grafana 패널로 조회해 사용자별 OpenAI-compatible token 사용량을 볼 수 있도록 한다. Control Plane/Client dashboard, request-level ledger, 사용자별 제한 enforcement는 만들지 않는다.
|
||
|
||
---
|
||
|
||
## Metric 목록
|
||
|
||
### 1. `iop_openai_usage_tokens_total` (Counter)
|
||
|
||
Provider-reported OpenAI-compatible token usage by token type.
|
||
|
||
| Label | Value 예시 | 설명 |
|
||
|-------|-----------|------|
|
||
| `edge_id` | `edge-1` | Edge instance identity |
|
||
| `principal_ref` | `usr-abc123` | Principal foreign-key-like reference |
|
||
| `principal_alias` | `john@acme` | Human-readable alias |
|
||
| `token_ref` | `tok-xyz789` | Token identity (not a raw secret) |
|
||
| `model_group` | `gpt-4o` | Model group identifier |
|
||
| `endpoint` | `chat.completions`, `responses` | OpenAI-compatible route |
|
||
| `response_mode` | `blocking`, `streaming` | Response mode |
|
||
| `token_type` | `input`, `output`, `reasoning`, `cached_input` | Token type |
|
||
|
||
### 2. `iop_openai_requests_total` (Counter)
|
||
|
||
OpenAI-compatible requests processed by terminal status and usage source.
|
||
|
||
| Label | Value 예시 | 설명 |
|
||
|-------|-----------|------|
|
||
| `edge_id` | `edge-1` | Edge instance identity |
|
||
| `principal_ref` | `usr-abc123` | Principal reference |
|
||
| `principal_alias` | `john@acme` | Human-readable alias |
|
||
| `token_ref` | `tok-xyz789` | Token identity |
|
||
| `model_group` | `gpt-4o` | Model group identifier |
|
||
| `endpoint` | `chat.completions`, `responses` | OpenAI-compatible route |
|
||
| `response_mode` | `blocking`, `streaming` | Response mode |
|
||
| `status` | `success`, `error`, `cancel` | Terminal request status |
|
||
| `usage_source` | `provider_reported`, `unavailable` | Whether at least one token type was reported |
|
||
|
||
### 3. `iop_openai_reasoning_observed_total` (Counter)
|
||
|
||
Requests where reasoning text was observed but the provider did not report reasoning token usage.
|
||
Same labels as `iop_openai_requests_total` excluding `status` and `usage_source`: `edge_id`, `principal_ref`, `principal_alias`, `token_ref`, `model_group`, `endpoint`, `response_mode`.
|
||
|
||
### 4. `iop_openai_reasoning_chars_total` (Counter)
|
||
|
||
Observed reasoning text characters for requests without provider-reported reasoning tokens. Never converted to a token estimate.
|
||
|
||
---
|
||
|
||
## Label Allowlist & Forbidden Labels
|
||
|
||
### 허용 label
|
||
|
||
```
|
||
edge_id, principal_ref, principal_alias, token_ref,
|
||
model_group, endpoint, response_mode, status,
|
||
token_type, usage_source
|
||
```
|
||
|
||
### 금지 label
|
||
|
||
- `request_id`, `session_id` — request-level 상세는 후속 ledger/Loki 축에서 다룬다.
|
||
- Bearer token, provider API key, raw payload, raw prompt/response text — secret 누출 방지 (SDD S08).
|
||
- 그 외 임의 label — cardinality 폭발을 막는다.
|
||
|
||
---
|
||
|
||
## PromQL Examples
|
||
|
||
### 기본: 사용자별 사용량 (principal_alias 기준)
|
||
|
||
```promql
|
||
# 입력 토큰 합계
|
||
sum by (principal_alias) (iop_openai_usage_tokens_total{token_type="input"})
|
||
|
||
# 출력 토큰 합계
|
||
sum by (principal_alias) (iop_openai_usage_tokens_total{token_type="output"})
|
||
```
|
||
|
||
### principal_ref별 usage breakdown
|
||
|
||
```promql
|
||
# principal_ref, token_type별 aggregation
|
||
sum by (principal_ref, token_type) (iop_openai_usage_tokens_total)
|
||
```
|
||
|
||
### token_ref별 사용량
|
||
|
||
```promql
|
||
# token_ref별 input/output 합계
|
||
sum by (token_ref, token_type) (iop_openai_usage_tokens_total)
|
||
```
|
||
|
||
### model_group별 usage
|
||
|
||
```promql
|
||
# model_group, token_type별 aggregation
|
||
sum by (model_group, token_type) (iop_openai_usage_tokens_total)
|
||
```
|
||
|
||
### endpoint별 요청 수
|
||
|
||
```promql
|
||
# endpoint, status별 요청 수
|
||
sum by (endpoint, status) (iop_openai_requests_total)
|
||
```
|
||
|
||
### response_mode별 분석
|
||
|
||
```promql
|
||
# response_mode별 성공 요청 수
|
||
sum by (response_mode, status) (iop_openai_requests_total{status="success"})
|
||
```
|
||
|
||
### token_type별 사용량 전체
|
||
|
||
```promql
|
||
# 모든 token_type별 합계 (time range 그래프용)
|
||
sum by (token_type) (irate(iop_openai_usage_tokens_total[5m]))
|
||
```
|
||
|
||
### usage_source별 요청 coverage
|
||
|
||
```promql
|
||
# provider_reported vs unavailable 비율
|
||
sum by (usage_source) (iop_openai_requests_total)
|
||
```
|
||
|
||
### reasoning 보조 metric
|
||
|
||
provider가 reasoning token을 보고하지 않는 경우:
|
||
|
||
```promql
|
||
# reasoning text가 관찰된 요청 수 (provider token 미보고)
|
||
sum by (principal_alias) (iop_openai_reasoning_observed_total)
|
||
|
||
# reasoning text character 합계
|
||
sum by (principal_alias) (iop_openai_reasoning_chars_total)
|
||
```
|
||
|
||
> **주의**: `iop_openai_reasoning_observed_total` / `iop_openai_reasoning_chars_total`는 provider-reported reasoning token이 있을 경우 emit되지 않는다. 즉, 이 metric은 "reasoning text는 있으나 token count 보고를 안 하는 provider"만 커버한다. token 추정을 위해 chars를 사용할 수 있으나 이 문서는 추정 권유를 하지 않는다.
|
||
|
||
---
|
||
|
||
## Dashboard Panel 후보
|
||
|
||
| 패널 | query | visualization |
|
||
|------|-------|---------------|
|
||
| 사용자별 token 사용량 (line) | `sum by (principal_alias, token_type) (irate(iop_openai_usage_tokens_total[5m]))` | Time series, legend=`{{principal_alias}} {{token_type}}` |
|
||
| model_group별 token 비율 (pie) | `sum by (model_group, token_type) (iop_openai_usage_tokens_total)` | Stat or bar chart |
|
||
| 요청 상태 분포 (table) | `sum by (endpoint, status, usage_source) (iop_openai_requests_total)` | Table |
|
||
| reasoning 보조 지표 (singlestat) | `sum(iop_openai_reasoning_observed_total)` | Singlestat |
|
||
|
||
> Grafana JSON dashboard import file은 본 scope에 포함되지 않는다. 위 PromQL을 바탕으로 패널을 수동 구성한다.
|
||
|
||
---
|
||
|
||
## daily / monthly Rollup
|
||
|
||
### 일일 토큰 합계
|
||
|
||
```promql
|
||
# 일일 입력/출력 토큰 합계 (principal_alias별)
|
||
sum by (principal_alias, token_type) (
|
||
increase(iop_openai_usage_tokens_total[1d])
|
||
)
|
||
```
|
||
|
||
> Grafana dashboard에서 `by time` aggregation으로 대체 가능:
|
||
> ```promql
|
||
> # Grafana 범용 aggregation (PromQL 함수 아님)
|
||
> # time range를 1일로 설정 후 sum by (principal_alias, token_type)
|
||
> iop_openai_usage_tokens_total
|
||
> ```
|
||
|
||
### 월간 토큰 합계
|
||
|
||
```promql
|
||
# 월간 입력/출력 토큰 합계 (principal_alias별)
|
||
sum by (principal_alias, token_type) (
|
||
increase(iop_openai_usage_tokens_total[30d])
|
||
)
|
||
```
|
||
|
||
> Grafana dashboard에서 범용 aggregation으로 대체 가능:
|
||
> ```promql
|
||
> # Grafana 범용 aggregation (PromQL 함수 아님)
|
||
> # time range를 30일로 설정 후 sum by (principal_alias, token_type)
|
||
> iop_openai_usage_tokens_total
|
||
> ```
|
||
|
||
### 일일/월간 rollup 활용 시나리오
|
||
|
||
- `principal_alias` 또는 `principal_ref`를 `by` clause에 추가해 사용자별 일일/월간 토큰 사용량을 산출한다.
|
||
- `token_type`을 함께 group by하면 input/output/reasoning/cached_input을 구분한다.
|
||
- `model_group`을 추가하면 모델별 비용 기반 추정 가능하다 (billing 산출은 이 문서 범위를 벗남).
|
||
|
||
---
|
||
|
||
## Limit Follow-up: 경계 명시
|
||
|
||
### 후속 Milestone으로 남기는 항목
|
||
|
||
- 사용자별 daily/monthly token **warn** 또는 **reject** enforcement는 이 Milestone의 범위가 아니며 후속 Milestone으로 Planned된다.
|
||
- billing, price, ROI amount 산출은 별도 ledger/cost model 범위다.
|
||
- request-level ledger / audit log는 Loki/queriable log축 후속 작업의 대상이다.
|
||
|
||
### 현재 문서가 제공하는 것
|
||
|
||
- `principal_ref`, `token_ref`, `model_group`, `token_type` 라벨 기반 daily/monthly rollup PromQL
|
||
- 사용자별 사용량 조회를 통한 운영 판단 기준
|
||
- provider reasoning report 누락 시 `reasoning_observed_total` / `reasoning_chars_total`로 보조 확인
|
||
|
||
이 rollup 기준은 후속 enforce Milestone에서 Prometheus query를 그대로 재사용할 수 있도록 설계되었다.
|
||
|
||
---
|
||
|
||
## Quick Reference: Label Values
|
||
|
||
| Label | 허용 값 |
|
||
|-------|---------|
|
||
| `endpoint` | `chat.completions`, `responses` |
|
||
| `status` | `success`, `error`, `cancel` |
|
||
| `usage_source` | `provider_reported`, `unavailable` |
|
||
| `token_type` | `input`, `output`, `reasoning`, `cached_input` |
|
||
| `response_mode` | `blocking`, `streaming` |
|
||
|
||
---
|
||
|
||
## Appendix: Grafana Scrape Target
|
||
|
||
Edge metrics는 보통 `localhost:19092` (local) 또는 해당 Edge metrics port에서 Prometheus scrape된다. Grafana data source에 Prometheus를 추가하고 위 PromQL을 테스트 패널에서 검증한다. |