Add OpenAPI specification for system-log service.
This commit is contained in:
parent
5f7fe11748
commit
f184c7b8d9
427
apps/system-log/openapi.yaml
Normal file
427
apps/system-log/openapi.yaml
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
openapi: 3.0.3
|
||||||
|
|
||||||
|
info:
|
||||||
|
title: system-log API
|
||||||
|
version: "1.0.0"
|
||||||
|
description: |
|
||||||
|
REST API сервиса **system-log** (`platform/system-log`) — приём и выборка
|
||||||
|
записей журнала системных событий (кто, над чем и какое действие совершил).
|
||||||
|
|
||||||
|
Сервис написан на Go (фреймворк **Fiber v2**). Роутинг собирается в
|
||||||
|
`internal/controller/http/v0`: базовая группа `/api` → подгруппа `v0` →
|
||||||
|
ресурс `/system_log`. Плюс служебный эндпоинт `/ping`.
|
||||||
|
|
||||||
|
### Аутентификация
|
||||||
|
Аутентификация на уровне приложения не настроена — эндпоинты доступны без
|
||||||
|
авторизации. Ограничение доступа обеспечивается сетевым слоем (ClusterIP /
|
||||||
|
Istio), а не самим сервисом.
|
||||||
|
|
||||||
|
### Пагинация
|
||||||
|
Списочные ответы возвращают объект `{ count, limit, offset, next, prev, result }`.
|
||||||
|
Управление — параметрами `limit` и `offset`. Значения по умолчанию:
|
||||||
|
`limit = 100`, `offset = 0` (константы `_defaultLimit` / `_defaultOffset`
|
||||||
|
в `internal/controller/http/v0/systemlog/controller.go`). Ссылки `next`/`prev`
|
||||||
|
формируются в `pkg/pagination`. У эндпоинта поиска (`POST /search`) полей
|
||||||
|
`next`/`prev` нет.
|
||||||
|
|
||||||
|
### Фильтрация
|
||||||
|
Массивные фильтры (`actor_ids`, `event_names`, `model_names`, `instance_ids`,
|
||||||
|
`target_ids`, `company_ids`, `statuses`, `message`) в GET-запросе передаются
|
||||||
|
списком значений через запятую и парсятся Fiber `QueryParser`. Поля
|
||||||
|
`instance_uuids` и `resource_uuids` разбираются вручную (`strings.Split` +
|
||||||
|
`uuid.Parse`) — при невалидном UUID возвращается `400`.
|
||||||
|
|
||||||
|
### Замечания (расхождения кода)
|
||||||
|
- `metadata` в фильтре объявлено как `map[string]interface{}` с query-тегом,
|
||||||
|
но при передаче в query-строке Fiber не восстановит вложенный объект —
|
||||||
|
фильтрация по `metadata` практически применима через тело `POST /search`.
|
||||||
|
- Поле `is_processed_by_worker` присутствует в фильтре, но отдаётся в выборку
|
||||||
|
наравне с остальными; используется воркером обогащения.
|
||||||
|
- Ответ `POST /system_log/` при успехе — простая строка `"OK"` (не объект).
|
||||||
|
|
||||||
|
servers:
|
||||||
|
- url: https://api.sarex.io
|
||||||
|
description: Production (ingress)
|
||||||
|
- url: https://stage-api.sarex.io
|
||||||
|
description: Stage (ingress)
|
||||||
|
- url: http://backend-svc.system-log.svc.cluster.local
|
||||||
|
description: Внутрикластерный адрес (ClusterIP, порт 80 → 8000)
|
||||||
|
- url: http://localhost:8888
|
||||||
|
description: Локальный запуск (config.env)
|
||||||
|
|
||||||
|
tags:
|
||||||
|
- name: system_log
|
||||||
|
description: Записи журнала системных событий
|
||||||
|
- name: service
|
||||||
|
description: Служебные эндпоинты
|
||||||
|
|
||||||
|
paths:
|
||||||
|
# ==========================================================================
|
||||||
|
# Service
|
||||||
|
# ==========================================================================
|
||||||
|
/ping:
|
||||||
|
get:
|
||||||
|
tags: [service]
|
||||||
|
summary: Проверка живости
|
||||||
|
description: Liveness/readiness-проба (используется в probes деплоймента). Всегда `200 OK` без тела.
|
||||||
|
operationId: ping
|
||||||
|
security: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
|
||||||
|
# ==========================================================================
|
||||||
|
# System log
|
||||||
|
# ==========================================================================
|
||||||
|
/api/v0/system_log/:
|
||||||
|
get:
|
||||||
|
tags: [system_log]
|
||||||
|
summary: Список записей журнала (с фильтрами)
|
||||||
|
description: |
|
||||||
|
Возвращает отфильтрованные записи журнала с пагинацией.
|
||||||
|
Массивные параметры принимают список значений через запятую.
|
||||||
|
operationId: getSystemLogRecords
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/Limit'
|
||||||
|
- $ref: '#/components/parameters/Offset'
|
||||||
|
- name: actor_ids
|
||||||
|
in: query
|
||||||
|
description: ID авторов событий; список значений через запятую
|
||||||
|
example: "1,2,3"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: event_names
|
||||||
|
in: query
|
||||||
|
description: Названия событий (напр. create, edit, delete, transfer); через запятую
|
||||||
|
example: "create,edit,delete"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: model_names
|
||||||
|
in: query
|
||||||
|
description: Названия моделей (напр. document, bundle, project); через запятую
|
||||||
|
example: "document,bundle"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: instance_ids
|
||||||
|
in: query
|
||||||
|
description: ID сущностей; список значений через запятую
|
||||||
|
example: "1,2,3"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: instance_uuids
|
||||||
|
in: query
|
||||||
|
description: UUID сущностей; список значений через запятую (валидируются как UUID)
|
||||||
|
example: "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: resource_uuids
|
||||||
|
in: query
|
||||||
|
description: UUID ресурсов; список значений через запятую (валидируются как UUID)
|
||||||
|
schema: { type: string }
|
||||||
|
- name: registered_at_gte
|
||||||
|
in: query
|
||||||
|
description: Нижняя граница времени регистрации (>=)
|
||||||
|
example: "2025-02-16T15:04:05Z"
|
||||||
|
schema: { type: string, format: date-time }
|
||||||
|
- name: registered_at_lte
|
||||||
|
in: query
|
||||||
|
description: Верхняя граница времени регистрации (<=)
|
||||||
|
example: "2025-02-16T15:04:05Z"
|
||||||
|
schema: { type: string, format: date-time }
|
||||||
|
- name: instance_path
|
||||||
|
in: query
|
||||||
|
description: Путь сущности (ltree), точное совпадение
|
||||||
|
example: "1.79899.80131"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: target_ids
|
||||||
|
in: query
|
||||||
|
description: ID целей; список значений через запятую
|
||||||
|
example: "1,2,3"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: target_path
|
||||||
|
in: query
|
||||||
|
description: Путь цели (ltree), точное совпадение
|
||||||
|
example: "4.3.2.1"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: company_ids
|
||||||
|
in: query
|
||||||
|
description: ID компаний; список значений через запятую
|
||||||
|
example: "1,2,3"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: statuses
|
||||||
|
in: query
|
||||||
|
description: Подстатусы события; список значений через запятую
|
||||||
|
example: "add_bundle,delete_bundle,rename_document"
|
||||||
|
schema: { type: string }
|
||||||
|
- name: message
|
||||||
|
in: query
|
||||||
|
description: Сообщения; список значений через запятую
|
||||||
|
schema: { type: string }
|
||||||
|
- name: is_processed_by_worker
|
||||||
|
in: query
|
||||||
|
description: Признак обработки записи воркером обогащения
|
||||||
|
schema: { type: boolean }
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema: { $ref: '#/components/schemas/SystemLogListResponse' }
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/BadRequest'
|
||||||
|
'500':
|
||||||
|
$ref: '#/components/responses/InternalError'
|
||||||
|
post:
|
||||||
|
tags: [system_log]
|
||||||
|
summary: Создать записи журнала
|
||||||
|
description: |
|
||||||
|
Принимает пакет записей в поле `system_logs`. Для каждой записи должно
|
||||||
|
быть задано **ровно одно** из `instance_id` / `instance_uuid`
|
||||||
|
(не оба и не ни одного — иначе `400`). Обязательны `event_name` и
|
||||||
|
`model_name`. При успехе возвращается строка `"OK"`.
|
||||||
|
operationId: createSystemLogRecords
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema: { $ref: '#/components/schemas/SystemLogCreateRequest' }
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Записи созданы
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: "OK"
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/BadRequest'
|
||||||
|
'500':
|
||||||
|
$ref: '#/components/responses/InternalError'
|
||||||
|
|
||||||
|
/api/v0/system_log/search:
|
||||||
|
post:
|
||||||
|
tags: [system_log]
|
||||||
|
summary: Поиск записей журнала (фильтры в теле)
|
||||||
|
description: |
|
||||||
|
Аналог GET-выборки, но фильтры передаются в теле запроса
|
||||||
|
(`filters`). Позволяет использовать сложные фильтры (в т.ч. `metadata`),
|
||||||
|
которые неудобно кодировать в query-строке. В ответе нет `next`/`prev`.
|
||||||
|
operationId: searchSystemLogs
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema: { $ref: '#/components/schemas/SystemLogSearchRequest' }
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema: { $ref: '#/components/schemas/SystemLogSearchResponse' }
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/BadRequest'
|
||||||
|
'500':
|
||||||
|
$ref: '#/components/responses/InternalError'
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
components:
|
||||||
|
parameters:
|
||||||
|
Limit:
|
||||||
|
name: limit
|
||||||
|
in: query
|
||||||
|
description: Кол-во записей на странице
|
||||||
|
schema: { type: integer, format: uint64, default: 100 }
|
||||||
|
Offset:
|
||||||
|
name: offset
|
||||||
|
in: query
|
||||||
|
description: Смещение от начала выборки
|
||||||
|
schema: { type: integer, format: uint64, default: 0, minimum: 0 }
|
||||||
|
|
||||||
|
responses:
|
||||||
|
BadRequest:
|
||||||
|
description: Ошибка разбора/валидации запроса
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema: { $ref: '#/components/schemas/ControllerError' }
|
||||||
|
InternalError:
|
||||||
|
description: Внутренняя ошибка сервиса
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema: { $ref: '#/components/schemas/ControllerError' }
|
||||||
|
|
||||||
|
schemas:
|
||||||
|
# ---- Общие ----
|
||||||
|
ControllerError:
|
||||||
|
type: object
|
||||||
|
description: Формат ошибки (`internal/controller/errors.go`, `ErrorToResponse`).
|
||||||
|
properties:
|
||||||
|
message: { type: string, example: "error parse body" }
|
||||||
|
status_code: { type: integer, example: 400 }
|
||||||
|
|
||||||
|
# ---- Доменная запись ----
|
||||||
|
SystemLog:
|
||||||
|
type: object
|
||||||
|
description: Запись журнала системных событий (`internal/entity/system_log.go`).
|
||||||
|
properties:
|
||||||
|
actor_id:
|
||||||
|
type: integer
|
||||||
|
format: uint64
|
||||||
|
description: ID автора события
|
||||||
|
example: 1023
|
||||||
|
event_name:
|
||||||
|
type: string
|
||||||
|
description: Название события (напр. edit, create, copy)
|
||||||
|
example: "edit"
|
||||||
|
model_name:
|
||||||
|
type: string
|
||||||
|
description: Над какой сущностью произошло событие (напр. document, inspection)
|
||||||
|
example: "document"
|
||||||
|
instance_id:
|
||||||
|
type: integer
|
||||||
|
format: uint64
|
||||||
|
nullable: true
|
||||||
|
description: ID сущности (для моделей с числовым ключом)
|
||||||
|
example: 80131
|
||||||
|
instance_uuid:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
description: UUID сущности (для моделей с UUID-ключом)
|
||||||
|
registered_at:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
nullable: true
|
||||||
|
description: Время регистрации события
|
||||||
|
example: "2023-05-04T08:09:53.852916Z"
|
||||||
|
instance_path:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Путь сущности (ltree)
|
||||||
|
example: "1.79899.80131"
|
||||||
|
target_id:
|
||||||
|
type: integer
|
||||||
|
format: uint64
|
||||||
|
nullable: true
|
||||||
|
description: ID цели события
|
||||||
|
company_id:
|
||||||
|
type: integer
|
||||||
|
format: uint64
|
||||||
|
nullable: true
|
||||||
|
description: ID компании (может обогащаться воркером)
|
||||||
|
example: 1
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
description: Произвольные дополнительные данные о событии
|
||||||
|
example: { "document_name": "КСГ.pdf", "count_bundle": 3 }
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Произвольное сообщение
|
||||||
|
example: "bundle was deleted from document"
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Подстатус события
|
||||||
|
example: "delete_bundle"
|
||||||
|
resource_uuid:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
description: UUID связанного ресурса
|
||||||
|
target_path:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Путь цели (ltree)
|
||||||
|
required: [event_name, model_name]
|
||||||
|
|
||||||
|
# ---- Запросы ----
|
||||||
|
SystemLogCreateRequest:
|
||||||
|
type: object
|
||||||
|
description: >
|
||||||
|
Пакет записей для создания. Для каждой записи обязательно ровно одно из
|
||||||
|
instance_id / instance_uuid.
|
||||||
|
properties:
|
||||||
|
system_logs:
|
||||||
|
type: array
|
||||||
|
minItems: 1
|
||||||
|
items: { $ref: '#/components/schemas/SystemLog' }
|
||||||
|
required: [system_logs]
|
||||||
|
|
||||||
|
SystemLogFilter:
|
||||||
|
type: object
|
||||||
|
description: Набор фильтров выборки (`entity.SystemLogFilter`).
|
||||||
|
properties:
|
||||||
|
limit: { type: integer, format: uint64, default: 100 }
|
||||||
|
offset: { type: integer, format: uint64, default: 0 }
|
||||||
|
actor_ids:
|
||||||
|
type: array
|
||||||
|
items: { type: integer, format: uint64 }
|
||||||
|
event_names:
|
||||||
|
type: array
|
||||||
|
items: { type: string }
|
||||||
|
model_names:
|
||||||
|
type: array
|
||||||
|
items: { type: string }
|
||||||
|
instance_ids:
|
||||||
|
type: array
|
||||||
|
items: { type: integer, format: uint64 }
|
||||||
|
instance_uuids:
|
||||||
|
type: array
|
||||||
|
items: { type: string, format: uuid }
|
||||||
|
registered_at_gte: { type: string, format: date-time, nullable: true }
|
||||||
|
registered_at_lte: { type: string, format: date-time, nullable: true }
|
||||||
|
instance_path: { type: string, nullable: true }
|
||||||
|
target_ids:
|
||||||
|
type: array
|
||||||
|
items: { type: integer, format: uint64 }
|
||||||
|
target_path: { type: string, nullable: true }
|
||||||
|
company_ids:
|
||||||
|
type: array
|
||||||
|
items: { type: integer, format: uint64 }
|
||||||
|
statuses:
|
||||||
|
type: array
|
||||||
|
items: { type: string }
|
||||||
|
message: { type: string, nullable: true }
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
resource_uuids:
|
||||||
|
type: array
|
||||||
|
items: { type: string, format: uuid }
|
||||||
|
is_processed_by_worker: { type: boolean, nullable: true }
|
||||||
|
|
||||||
|
SystemLogSearchRequest:
|
||||||
|
type: object
|
||||||
|
description: Тело запроса поиска (`SearchParams` в `dto.go`).
|
||||||
|
properties:
|
||||||
|
limit: { type: integer, format: uint64, default: 100 }
|
||||||
|
offset: { type: integer, format: uint64, default: 0 }
|
||||||
|
filters: { $ref: '#/components/schemas/SystemLogFilter' }
|
||||||
|
|
||||||
|
# ---- Ответы ----
|
||||||
|
SystemLogListResponse:
|
||||||
|
type: object
|
||||||
|
description: Ответ списочной выборки (`entity.SystemLogRecordsRequest`).
|
||||||
|
properties:
|
||||||
|
count: { type: integer, format: uint64, example: 1226 }
|
||||||
|
limit: { type: integer, format: uint64, nullable: true, example: 100 }
|
||||||
|
offset: { type: integer, format: uint64, nullable: true, example: 0 }
|
||||||
|
next:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
example: "http://localhost:8888/api/v0/system_log?limit=100&offset=100"
|
||||||
|
prev:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
result:
|
||||||
|
type: array
|
||||||
|
items: { $ref: '#/components/schemas/SystemLog' }
|
||||||
|
required: [count, result]
|
||||||
|
|
||||||
|
SystemLogSearchResponse:
|
||||||
|
type: object
|
||||||
|
description: Ответ поиска (`entity.SystemLogRecordsSearch`) — без next/prev.
|
||||||
|
properties:
|
||||||
|
count: { type: integer, format: uint64, example: 1226 }
|
||||||
|
limit: { type: integer, format: uint64, nullable: true, example: 100 }
|
||||||
|
offset: { type: integer, format: uint64, nullable: true, example: 0 }
|
||||||
|
result:
|
||||||
|
type: array
|
||||||
|
items: { $ref: '#/components/schemas/SystemLog' }
|
||||||
|
required: [count, result]
|
||||||
Loading…
Reference in New Issue
Block a user