- Added a new endpoint `/api/agg/incidents` to provide a normalized snapshot of incidents for fleet triage, including severity and recommended actions. - Implemented live event streaming via `/api/live/events` for real-time updates on fleet status and incidents, enhancing observability. - Updated the Web UI to include dedicated sections for incidents and live updates, improving user navigation and access to critical information. - Enhanced API documentation to reflect new endpoints and their functionalities, ensuring clarity for developers and users.
359 lines
11 KiB
YAML
359 lines
11 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: Telemt API gateway — aggregate API
|
|
description: >
|
|
Эндпоинты под префиксом /api/agg на шлюзе telemt-api.
|
|
Базовый URL задаётся listen шлюза (например http://127.0.0.1:8080).
|
|
version: 1.0.0
|
|
|
|
paths:
|
|
/api/agg/summary:
|
|
get:
|
|
summary: Сводка флота и топы пользователей
|
|
parameters:
|
|
- $ref: '#/components/parameters/aliases'
|
|
- name: top_n
|
|
in: query
|
|
schema: { type: integer, minimum: 1, maximum: 1000, default: 10 }
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/AggEnvelopeSummary' }
|
|
|
|
/api/agg/traffic:
|
|
get:
|
|
summary: Трафик по пользователям и серверам
|
|
parameters:
|
|
- $ref: '#/components/parameters/aliases'
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/AggEnvelopeTrafficRows' }
|
|
|
|
/api/agg/unique-ips:
|
|
get:
|
|
summary: Уникальные IP с привязкой к серверам (и опционально GeoIP)
|
|
parameters:
|
|
- $ref: '#/components/parameters/aliases'
|
|
- name: geo
|
|
in: query
|
|
description: 'false — не обогащать GeoIP'
|
|
schema: { type: string, enum: ['false', 'true'] }
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/AggEnvelopeUniqueIPs' }
|
|
|
|
/api/agg/users:
|
|
get:
|
|
summary: Список пользователей с merge по серверам
|
|
parameters:
|
|
- $ref: '#/components/parameters/aliases'
|
|
- name: include_links
|
|
in: query
|
|
schema: { type: string, enum: ['true', 'false'] }
|
|
- name: min_total_megabytes
|
|
in: query
|
|
schema: { type: number, format: float }
|
|
- name: min_total_octets
|
|
in: query
|
|
schema: { type: string }
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/AggEnvelopeUsersRows' }
|
|
|
|
/api/agg/user/{username}:
|
|
get:
|
|
summary: Один пользователь (тот же объект, что в users[])
|
|
parameters:
|
|
- name: username
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
pattern: '^[A-Za-z0-9_.-]+$'
|
|
- $ref: '#/components/parameters/aliases'
|
|
- name: include_links
|
|
in: query
|
|
schema: { type: string, enum: ['true', 'false'] }
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/AggEnvelopeUsersRow' }
|
|
'404':
|
|
description: Пользователь не найден ни на одном upstream
|
|
|
|
/api/agg/fleet-status:
|
|
get:
|
|
summary: Health + system/info по всем выбранным серверам
|
|
parameters:
|
|
- $ref: '#/components/parameters/aliases'
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/AggEnvelopeFleetStatus' }
|
|
|
|
/api/agg/incidents:
|
|
get:
|
|
summary: Нормализованный snapshot инцидентов по флоту
|
|
parameters:
|
|
- $ref: '#/components/parameters/aliases'
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema: { $ref: '#/components/schemas/AggEnvelopeIncidents' }
|
|
|
|
components:
|
|
parameters:
|
|
aliases:
|
|
name: aliases
|
|
in: query
|
|
description: Список алиасов через запятую
|
|
schema: { type: string }
|
|
|
|
schemas:
|
|
AggSuccessBase:
|
|
type: object
|
|
required: [ok, data, generated_at]
|
|
properties:
|
|
ok: { type: boolean, enum: [true] }
|
|
generated_at: { type: string, format: date-time }
|
|
partial: { type: boolean, description: true если часть upstream недоступна }
|
|
|
|
AggEnvelopeSummary:
|
|
allOf:
|
|
- $ref: '#/components/schemas/AggSuccessBase'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: object
|
|
description: SummaryData (см. реализацию / доку AGGREGATE.md)
|
|
|
|
AggEnvelopeTrafficRows:
|
|
allOf:
|
|
- $ref: '#/components/schemas/AggSuccessBase'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/TrafficRow' }
|
|
|
|
AggEnvelopeUniqueIPs:
|
|
allOf:
|
|
- $ref: '#/components/schemas/AggSuccessBase'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/UniqueIPsRow' }
|
|
|
|
AggEnvelopeUsersRows:
|
|
allOf:
|
|
- $ref: '#/components/schemas/AggSuccessBase'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/UsersRow' }
|
|
|
|
AggEnvelopeUsersRow:
|
|
allOf:
|
|
- $ref: '#/components/schemas/AggSuccessBase'
|
|
- type: object
|
|
properties:
|
|
data: { $ref: '#/components/schemas/UsersRow' }
|
|
|
|
AggEnvelopeFleetStatus:
|
|
allOf:
|
|
- $ref: '#/components/schemas/AggSuccessBase'
|
|
- type: object
|
|
properties:
|
|
data: { $ref: '#/components/schemas/FleetStatusData' }
|
|
|
|
AggEnvelopeIncidents:
|
|
allOf:
|
|
- $ref: '#/components/schemas/AggSuccessBase'
|
|
- type: object
|
|
properties:
|
|
data: { $ref: '#/components/schemas/IncidentsData' }
|
|
|
|
TrafficRow:
|
|
type: object
|
|
properties:
|
|
username: { type: string }
|
|
servers:
|
|
type: object
|
|
additionalProperties:
|
|
$ref: '#/components/schemas/TrafficServerStats'
|
|
|
|
TrafficServerStats:
|
|
type: object
|
|
properties:
|
|
total_megabytes: { type: number, format: float }
|
|
current_connections: { type: integer, format: int64 }
|
|
revision: { type: string }
|
|
|
|
UniqueIPsRow:
|
|
type: object
|
|
properties:
|
|
username: { type: string }
|
|
ips:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/IPAssignments' }
|
|
|
|
IPAssignments:
|
|
type: object
|
|
properties:
|
|
ip: { type: string }
|
|
active_on_servers:
|
|
type: array
|
|
items: { type: string }
|
|
recent_on_servers:
|
|
type: array
|
|
items: { type: string }
|
|
primary_server: { type: string, nullable: true }
|
|
country_code: { type: string, nullable: true }
|
|
country_name: { type: string, nullable: true }
|
|
city_name: { type: string, nullable: true }
|
|
latitude: { type: number, format: float, nullable: true }
|
|
longitude: { type: number, format: float, nullable: true }
|
|
asn: { type: integer, format: int64, nullable: true }
|
|
as_organization: { type: string, nullable: true }
|
|
|
|
UserLinks:
|
|
type: object
|
|
properties:
|
|
classic:
|
|
type: array
|
|
items: { type: string }
|
|
secure:
|
|
type: array
|
|
items: { type: string }
|
|
tls:
|
|
type: array
|
|
items: { type: string }
|
|
|
|
UsersRow:
|
|
type: object
|
|
properties:
|
|
username: { type: string }
|
|
total_megabytes: { type: number, format: float }
|
|
by_server:
|
|
type: object
|
|
additionalProperties:
|
|
$ref: '#/components/schemas/TrafficServerStats'
|
|
links: { $ref: '#/components/schemas/UserLinks' }
|
|
active_unique_ips: { type: integer, format: int64 }
|
|
recent_unique_ips: { type: integer, format: int64 }
|
|
user_ad_tag: { type: string, nullable: true }
|
|
max_tcp_conns: { type: integer, format: int64, nullable: true }
|
|
expiration_rfc3339: { type: string, nullable: true }
|
|
data_quota_bytes: { type: integer, format: int64, nullable: true }
|
|
max_unique_ips: { type: integer, format: int64, nullable: true }
|
|
|
|
HealthData:
|
|
type: object
|
|
properties:
|
|
status: { type: string }
|
|
read_only: { type: boolean }
|
|
|
|
SystemInfoData:
|
|
type: object
|
|
properties:
|
|
version: { type: string }
|
|
target_arch: { type: string }
|
|
target_os: { type: string }
|
|
build_profile: { type: string }
|
|
git_commit: { type: string, nullable: true }
|
|
build_time_utc: { type: string, nullable: true }
|
|
rustc_version: { type: string, nullable: true }
|
|
process_started_at_epoch_secs: { type: integer, format: int64 }
|
|
uptime_seconds: { type: number, format: float }
|
|
config_path: { type: string }
|
|
config_hash: { type: string }
|
|
config_reload_count: { type: integer, format: int64 }
|
|
last_config_reload_epoch_secs: { type: integer, format: int64, nullable: true }
|
|
|
|
FleetServerStatus:
|
|
type: object
|
|
properties:
|
|
alias: { type: string }
|
|
ok: { type: boolean }
|
|
health_ok: { type: boolean }
|
|
health_http_status: { type: integer }
|
|
health_latency_ms: { type: integer, format: int64 }
|
|
health_error: { type: string }
|
|
health_revision: { type: string }
|
|
health: { $ref: '#/components/schemas/HealthData' }
|
|
system_info_ok: { type: boolean }
|
|
system_info_http_status: { type: integer }
|
|
system_info_latency_ms: { type: integer, format: int64 }
|
|
system_info_error: { type: string }
|
|
system_info_revision: { type: string }
|
|
system_info: { $ref: '#/components/schemas/SystemInfoData' }
|
|
|
|
FleetStatusData:
|
|
type: object
|
|
properties:
|
|
servers:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/FleetServerStatus' }
|
|
servers_total: { type: integer }
|
|
servers_all_ok: { type: integer }
|
|
servers_failed: { type: integer }
|
|
|
|
IncidentAction:
|
|
type: object
|
|
properties:
|
|
label: { type: string }
|
|
href: { type: string }
|
|
|
|
IncidentItem:
|
|
type: object
|
|
properties:
|
|
id: { type: string }
|
|
kind: { type: string }
|
|
severity:
|
|
type: string
|
|
enum: [info, warning, critical]
|
|
status:
|
|
type: string
|
|
enum: [firing]
|
|
title: { type: string }
|
|
summary: { type: string }
|
|
affected_aliases:
|
|
type: array
|
|
items: { type: string }
|
|
metric_name: { type: string }
|
|
metric_value: { type: number, format: float }
|
|
metric_threshold: { type: number, format: float }
|
|
actions:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/IncidentAction' }
|
|
|
|
IncidentsData:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items: { $ref: '#/components/schemas/IncidentItem' }
|
|
total: { type: integer }
|
|
critical_total: { type: integer }
|
|
warning_total: { type: integer }
|
|
info_total: { type: integer }
|