- Создан основной README.md с описанием проекта - Добавлена подробная документация в папке docs/ - Создан файл LICENSE (MIT) - Обновлен .gitignore - Добавлена документация по безопасности с генерацией ключей - Включены примеры конфигураций и устранение неполадок Автор: Сергей Антропов Сайт: https://devops.org.ru
16 KiB
API Документация LogBoard+
Автор: Сергей Антропов
Сайт: https://devops.org.ru
Содержание
Обзор API
LogBoard+ предоставляет REST API и WebSocket API для работы с логами Docker контейнеров.
Базовый URL
http://localhost:9001
Форматы данных
- Content-Type:
application/json
- Кодировка: UTF-8
- Временные метки: ISO 8601 (UTC)
Аутентификация
Все API endpoints (кроме /healthz
и /api/auth/login
) требуют JWT токен в заголовке:
Authorization: Bearer <token>
Аутентификация
POST /api/auth/login
Вход в систему и получение JWT токена.
Запрос:
{
"username": "admin",
"password": "your-password"
}
Ответ:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}
Пример curl:
curl -X POST "http://localhost:9001/api/auth/login" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"your-password"}'
POST /api/auth/logout
Выход из системы (удаление токена из cookies).
Ответ:
{
"message": "Успешный выход из системы"
}
GET /api/auth/me
Получение информации о текущем пользователе.
Заголовки:
Authorization: Bearer <token>
Ответ:
{
"username": "admin"
}
REST API
Контейнеры и сервисы
GET /api/services
Получение списка всех контейнеров.
Параметры запроса:
Параметр | Тип | Описание | По умолчанию |
---|---|---|---|
projects |
string | Фильтр по проектам (через запятую) | Все проекты |
include_stopped |
boolean | Включить остановленные контейнеры | false |
Пример запроса:
curl -X GET "http://localhost:9001/api/services?projects=myproject&include_stopped=true" \
-H "Authorization: Bearer YOUR_TOKEN"
Ответ:
[
{
"id": "abc123def456",
"name": "myproject_web_1",
"status": "running",
"image": "nginx:latest",
"service": "web",
"project": "myproject",
"health": "healthy",
"ports": ["80/tcp"],
"url": "http://localhost:8080",
"host_port": "8080"
},
{
"id": "def456ghi789",
"name": "myproject_db_1",
"status": "running",
"image": "postgres:13",
"service": "db",
"project": "myproject",
"health": "healthy",
"ports": ["5432/tcp"],
"url": null,
"host_port": null
}
]
GET /api/projects
Получение списка всех проектов Docker Compose.
Ответ:
[
"myproject",
"another-project",
"standalone"
]
Логи
GET /api/logs/{container_id}
Получение логов контейнера.
Параметры пути:
container_id
- ID контейнера (первые 12 символов)
Параметры запроса:
Параметр | Тип | Описание | По умолчанию |
---|---|---|---|
tail |
string | Количество строк или 'all' | 500 |
since |
string | Время начала (ISO 8601 или относительное) | null |
Пример запроса:
curl -X GET "http://localhost:9001/api/logs/abc123def456?tail=100&since=2024-01-15T10:00:00Z" \
-H "Authorization: Bearer YOUR_TOKEN"
Ответ:
{
"container": {
"id": "abc123def456",
"name": "myproject_web_1",
"status": "running",
"image": "nginx:latest",
"created": "2024-01-15T09:00:00.000000000Z",
"state": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 1234,
"ExitCode": 0,
"Error": "",
"StartedAt": "2024-01-15T09:00:00.000000000Z",
"FinishedAt": "0001-01-01T00:00:00Z"
}
},
"logs": [
{
"timestamp": "2024-01-15T10:30:15.123456789Z",
"message": "2024/01/15 10:30:15 [notice] 1#1: start worker processes",
"raw": "2024-01-15T10:30:15.123456789Z 2024/01/15 10:30:15 [notice] 1#1: start worker processes"
},
{
"timestamp": "2024-01-15T10:30:15.123456789Z",
"message": "2024/01/15 10:30:15 [notice] 1#1: start worker process 1234",
"raw": "2024-01-15T10:30:15.123456789Z 2024/01/15 10:30:15 [notice] 1#1: start worker process 1234"
}
],
"total_lines": 2,
"tail": "100",
"since": "2024-01-15T10:00:00Z",
"timestamp": "2024-01-15T10:30:15.123456789Z"
}
GET /api/logs/stats/{container_id}
Получение статистики логов контейнера.
Ответ:
{
"debug": 15,
"info": 42,
"warn": 8,
"error": 3
}
Управление
GET /api/settings
Получение настроек приложения.
Ответ:
{
"ajax_update_interval": 2000,
"default_tail": 500,
"skip_unhealthy": true
}
GET /api/excluded-containers
Получение списка исключенных контейнеров.
Ответ:
{
"excluded_containers": [
"noisy-container-1",
"noisy-container-2"
]
}
POST /api/excluded-containers
Обновление списка исключенных контейнеров.
Запрос:
[
"noisy-container-1",
"noisy-container-2",
"another-noisy-container"
]
Ответ:
{
"status": "success",
"message": "Список исключенных контейнеров обновлен"
}
POST /api/snapshot
Создание снимка логов.
Запрос:
{
"container_id": "abc123def456",
"service": "web",
"content": "Логи контейнера..."
}
Ответ:
{
"file": "web-20240115-103015.log",
"url": "/snapshots/web-20240115-103015.log"
}
Системные
GET /healthz
Health check endpoint.
Ответ:
ok
WebSocket API
Подключение
Все WebSocket endpoints требуют JWT токен в параметре token
.
ws://host:port/ws/logs/{container_id}
Получение логов отдельного контейнера.
Параметры:
container_id
- ID контейнераtail
- Количество строк (по умолчанию 500)token
- JWT токенservice
- Имя сервиса (опционально)project
- Имя проекта (опционально)
Пример подключения:
const token = "your-jwt-token";
const containerId = "abc123def456";
const ws = new WebSocket(`ws://localhost:9001/ws/logs/${containerId}?token=${token}&tail=100`);
ws.onmessage = function(event) {
console.log('Получены логи:', event.data);
};
ws.onerror = function(error) {
console.error('WebSocket ошибка:', error);
};
ws://host:port/ws/fan/{service_name}
Получение логов сервиса (все реплики).
Параметры:
service_name
- Имя сервиса Docker Composetail
- Количество строк (по умолчанию 500)token
- JWT токенproject
- Имя проекта (опционально)
Пример подключения:
const token = "your-jwt-token";
const serviceName = "web";
const ws = new WebSocket(`ws://localhost:9001/ws/fan/${serviceName}?token=${token}&tail=100`);
ws.onmessage = function(event) {
console.log('Логи сервиса:', event.data);
};
ws://host:port/ws/fan_group
Получение логов группы сервисов.
Параметры:
services
- Имена сервисов через запятуюtail
- Количество строк (по умолчанию 500)token
- JWT токенproject
- Имя проекта (опционально)
Пример подключения:
const token = "your-jwt-token";
const services = "web,db,redis";
const ws = new WebSocket(`ws://localhost:9001/ws/fan_group?services=${services}&token=${token}&tail=100`);
ws.onmessage = function(event) {
console.log('Логи группы сервисов:', event.data);
};
Коды ошибок
HTTP коды состояния
Код | Описание |
---|---|
200 | Успешный запрос |
400 | Неверный запрос |
401 | Не авторизован |
403 | Доступ запрещен |
404 | Ресурс не найден |
500 | Внутренняя ошибка сервера |
Формат ошибок
{
"error": "error_type",
"message": "Описание ошибки",
"details": "Дополнительная информация"
}
Примеры ошибок
401 Unauthorized
{
"error": "unauthorized",
"message": "Требуется авторизация",
"details": "Для доступа к этому API необходимо войти в систему."
}
404 Not Found
{
"error": "http_404",
"message": "Контейнер не найден",
"details": "URL: /api/logs/invalid-id"
}
500 Internal Server Error
{
"error": "http_500",
"message": "Ошибка подключения к Docker",
"details": "URL: /api/services"
}
Примеры использования
Python
import requests
import json
# Базовый URL
BASE_URL = "http://localhost:9001"
# Аутентификация
def login(username, password):
response = requests.post(f"{BASE_URL}/api/auth/login", json={
"username": username,
"password": password
})
return response.json()["access_token"]
# Получение списка контейнеров
def get_containers(token):
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(f"{BASE_URL}/api/services", headers=headers)
return response.json()
# Получение логов контейнера
def get_logs(token, container_id, tail=100):
headers = {"Authorization": f"Bearer {token}"}
params = {"tail": tail}
response = requests.get(f"{BASE_URL}/api/logs/{container_id}",
headers=headers, params=params)
return response.json()
# Использование
token = login("admin", "your-password")
containers = get_containers(token)
print(f"Найдено контейнеров: {len(containers)}")
for container in containers:
logs = get_logs(token, container["id"], tail=10)
print(f"Контейнер {container['name']}: {len(logs['logs'])} строк логов")
JavaScript
// Класс для работы с LogBoard+ API
class LogBoardAPI {
constructor(baseUrl, token) {
this.baseUrl = baseUrl;
this.token = token;
this.headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
}
// Получение списка контейнеров
async getContainers(projects = null, includeStopped = false) {
const params = new URLSearchParams();
if (projects) params.append('projects', projects);
if (includeStopped) params.append('include_stopped', 'true');
const response = await fetch(`${this.baseUrl}/api/services?${params}`, {
headers: this.headers
});
return await response.json();
}
// Получение логов контейнера
async getLogs(containerId, tail = 100, since = null) {
const params = new URLSearchParams();
params.append('tail', tail);
if (since) params.append('since', since);
const response = await fetch(`${this.baseUrl}/api/logs/${containerId}?${params}`, {
headers: this.headers
});
return await response.json();
}
// Получение статистики логов
async getLogStats(containerId) {
const response = await fetch(`${this.baseUrl}/api/logs/stats/${containerId}`, {
headers: this.headers
});
return await response.json();
}
// WebSocket для live-логов
createLogsWebSocket(containerId, tail = 100) {
const ws = new WebSocket(
`ws://${this.baseUrl.replace('http://', '')}/ws/logs/${containerId}?token=${this.token}&tail=${tail}`
);
return ws;
}
}
// Использование
async function main() {
// Получение токена
const loginResponse = await fetch('http://localhost:9001/api/auth/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
username: 'admin',
password: 'your-password'
})
});
const {access_token} = await loginResponse.json();
// Создание API клиента
const api = new LogBoardAPI('http://localhost:9001', access_token);
// Получение контейнеров
const containers = await api.getContainers();
console.log('Контейнеры:', containers);
// Получение логов первого контейнера
if (containers.length > 0) {
const logs = await api.getLogs(containers[0].id, 50);
console.log('Логи:', logs);
// WebSocket для live-логов
const ws = api.createLogsWebSocket(containers[0].id, 100);
ws.onmessage = (event) => {
console.log('Новые логи:', event.data);
};
}
}
main().catch(console.error);
cURL
#!/bin/bash
# Переменные
BASE_URL="http://localhost:9001"
USERNAME="admin"
PASSWORD="your-password"
# Получение токена
TOKEN=$(curl -s -X POST "$BASE_URL/api/auth/login" \
-H "Content-Type: application/json" \
-d "{\"username\":\"$USERNAME\",\"password\":\"$PASSWORD\"}" \
| jq -r '.access_token')
echo "Токен получен: ${TOKEN:0:20}..."
# Получение списка контейнеров
echo "Получение списка контейнеров..."
curl -s -X GET "$BASE_URL/api/services" \
-H "Authorization: Bearer $TOKEN" \
| jq '.[] | {name: .name, status: .status, project: .project}'
# Получение логов первого контейнера
CONTAINER_ID=$(curl -s -X GET "$BASE_URL/api/services" \
-H "Authorization: Bearer $TOKEN" \
| jq -r '.[0].id')
echo "Получение логов контейнера $CONTAINER_ID..."
curl -s -X GET "$BASE_URL/api/logs/$CONTAINER_ID?tail=10" \
-H "Authorization: Bearer $TOKEN" \
| jq '.logs[] | .message'
Ограничения и рекомендации
Ограничения
- Максимальное количество строк логов: 10000
- Таймаут WebSocket соединения: 60 секунд
- Максимальный размер снимка логов: 10 MB
Рекомендации
- Используйте фильтрацию по времени для больших объемов логов
- Настройте исключение контейнеров с избыточным логированием
- Используйте WebSocket для real-time мониторинга
- Регулярно очищайте снимки логов для экономии места
Производительность
- REST API: до 1000 запросов в минуту
- WebSocket: до 100 одновременных соединений
- Размер ответа: до 1 MB на запрос