Skip to content
Merged

123 #52

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9aa8b7d
fix: update Go version to 1.26 to resolve security vulnerabilities
godofphonk Mar 7, 2026
488e89b
feat: add migration for server source identifiers table
godofphonk Mar 8, 2026
e2a2cb8
feat: add server source identifiers models
godofphonk Mar 8, 2026
a93420e
feat: add server source identifiers repository interface
godofphonk Mar 8, 2026
7c7e395
feat: implement PostgreSQL repository for server identifiers
godofphonk Mar 8, 2026
69b6bf5
feat: add server service methods for identifiers
godofphonk Mar 8, 2026
87cd053
feat: add API routes for server source identifiers
godofphonk Mar 8, 2026
b6188e7
feat: complete server source identifiers implementation
godofphonk Mar 8, 2026
fed5bd5
added migration in cd
godofphonk Mar 8, 2026
40b253e
feat: add telegram_id field for account linking
godofphonk Mar 8, 2026
cee06e0
feat: add UpdateTelegramID endpoint for linking accounts
godofphonk Mar 8, 2026
deb2403
fix: properly handle telegram_id pointer values in SQL queries
godofphonk Mar 8, 2026
ad0da45
refactor: reorganize database migrations by database type
godofphonk Mar 8, 2026
684b4df
fix: update docker-compose paths after migration reorganization
godofphonk Mar 9, 2026
338d70d
fix: prevent panic in StaticInfoHandler when storage is nil
godofphonk Mar 9, 2026
b5e6d28
fix: support decimal values for hardware specs
godofphonk Mar 9, 2026
bf59337
feat: implement agent static info HTTP endpoint with enhanced logging
godofphonk Mar 9, 2026
00e7455
docs: add data structure separation plan and new metrics models
godofphonk Mar 9, 2026
9f64c98
feat(websocket): add support for MetricsV2 format with nested structure
godofphonk Mar 9, 2026
5501ea2
feat(handlers): add MetricsV2 support to HTTP POST endpoint
godofphonk Mar 9, 2026
20e32a6
feat(services): enhance metrics API response with detailed V2 data
godofphonk Mar 9, 2026
99d3c1d
feat: add backward compatibility for Telegram ID search
godofphonk Mar 13, 2026
66e79cc
docs: simplify README structure
godofphonk Mar 13, 2026
fcdfd4a
ci: fix GitHub Actions workflow issues
godofphonk Mar 13, 2026
b1ff321
fix: remove identifiers when deleting server source
godofphonk Mar 13, 2026
5490312
feat: add granular source identifier deletion
godofphonk Mar 13, 2026
7bb96b6
feat: add TimescaleDB multi-tier metrics CI/CD support
godofphonk Mar 22, 2026
5e3b67e
fix: fixed timescale metrics support tiered endpoint
godofphonk Mar 22, 2026
1107eb6
feat(tiered-metrics): add server_key support for tiered metrics endpoint
godofphonk Mar 22, 2026
74ea1ae
feat: optimize metrics granularity for better visualization
godofphonk Mar 22, 2026
8b0d73b
ci: add optimized granularity migrations to pipeline
godofphonk Mar 22, 2026
834be55
feat: add unified server endpoint
godofphonk Mar 23, 2026
3bae4fb
fix(server): prevent duplicate source error
godofphonk Mar 23, 2026
2b7ac8e
fix(database): correct static data connection and container naming
godofphonk Apr 3, 2026
0e704c4
ci: fix production deployment for new and existing VPS
godofphonk Apr 3, 2026
9b30de8
fix(ci): resolve compilation errors and sarif file issues
godofphonk Apr 3, 2026
1676238
style: format code with gofmt
godofphonk Apr 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 168 additions & 60 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# SOFTWARE.

# Build stage
FROM golang:1.25-alpine AS builder
FROM golang:1.26-alpine AS builder

# Install git and ca-certificates
RUN apk add --no-cache git ca-certificates tzdata
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,19 @@ docker-compose-down:
docker-compose-logs:
docker-compose logs -f

# Database management
db-migrate:
@echo "🗄️ Running database migrations..."
docker exec -i ServereyeAPI-timescaledb psql -U postgres -d servereye < deployments/timescaledb/timescaledb-multi-tier.sql

db-status:
@echo "📊 Checking database status..."
docker exec ServereyeAPI-timescaledb psql -U postgres -d servereye -c "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name LIKE 'metrics_%_avg' ORDER BY table_name;"
Comment on lines +150 to +154
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The db-* targets exec into ServereyeAPI-timescaledb, but docker-compose now names the container ServerEyeAPI-timescaledb. As written, these targets will fail to find the container; update the container name (or derive it via docker compose ps -q api-timescaledb).

Suggested change
docker exec -i ServereyeAPI-timescaledb psql -U postgres -d servereye < deployments/timescaledb/timescaledb-multi-tier.sql
db-status:
@echo "📊 Checking database status..."
docker exec ServereyeAPI-timescaledb psql -U postgres -d servereye -c "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name LIKE 'metrics_%_avg' ORDER BY table_name;"
docker exec -i $$(docker compose ps -q api-timescaledb) psql -U postgres -d servereye < deployments/timescaledb/timescaledb-multi-tier.sql
db-status:
@echo "📊 Checking database status..."
docker exec $$(docker compose ps -q api-timescaledb) psql -U postgres -d servereye -c "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name LIKE 'metrics_%_avg' ORDER BY table_name;"

Copilot uses AI. Check for mistakes.

db-test:
@echo "🧪 Testing multi-tier metrics..."
curl -s "http://localhost:8080/api/servers/srv_17fdfe6d/metrics/tiered?start=$$(date -d '1 hour ago' -Iseconds)&end=$$(date -Iseconds)" | jq '{server_id, granularity, total_points}'

# Release build with optimizations and version
RELEASE_LDFLAGS = -w -s \
-X github.com/godofphonk/ServerEyeAPI/internal/version.Version=$(VERSION) \
Expand Down Expand Up @@ -196,6 +209,11 @@ help:
@echo " docker-compose-down - Stop services"
@echo " docker-compose-logs - View service logs"
@echo ""
@echo "Database:"
@echo " db-migrate - Run TimescaleDB migrations"
@echo " db-status - Check database aggregates status"
@echo " db-test - Test multi-tier metrics endpoint"
@echo ""
@echo "Utilities:"
@echo " clean - Clean build artifacts"
@echo " deps - Download dependencies"
Expand Down
334 changes: 1 addition & 333 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,333 +1 @@
# ServerEyeAPI

[![Go Report Card](https://goreportcard.com/badge/github.com/godofphonk/ServerEyeAPI)](https://goreportcard.com/report/github.com/godofphonk/ServerEyeAPI)

## Base URL

```text
https://api.servereye.dev
```

## Authentication

ServerEyeAPI supports multiple authentication methods:

### 1. API Key Authentication (Recommended)

For service-to-service communication.

**Headers:**

```text
X-API-Key: sk_your_api_key_here
```

**Default Development Key:**

```text
sk_csharp_backend_development_key_change_in_production
```

### 2. Server Key Authentication

For server agents and basic endpoints using server-specific keys.

### 3. Bearer Token Authentication

For protected admin endpoints (marked with 🔒).

## Core Endpoints

### 🔓 Health Check

**Endpoint:** `GET /health`

**Response:**

```json
{
"status": "healthy",
"timestamp": "2026-02-18T09:12:12Z",
"version": "1.0.0"
}
```

---

### 🔓 Server Registration

**Endpoint:** `POST /RegisterKey`

**Request:**

```json
{
"hostname": "server-01",
"operating_system": "Ubuntu 22.04",
"agent_version": "1.0.0"
}
```

**Response:**

```json
{
"server_id": "srv_123456789",
"server_key": "sk_abcdef123456",
"status": "registered"
}
```

---

### 🔓 Metrics - Unified Tiered Endpoint

**Endpoint:** `GET /api/servers/{server_id}/metrics/tiered`

**Query Parameters:**
- `start` (string, required): Start time (RFC3339 format)
- `end` (string, required): End time (RFC3339 format)

**Auto-Granularity Strategy:**
- **Last hour**: 1-minute intervals

- **Last 3 hours**: 5-minute intervals

- **Last 24 hours**: 10-minute intervals

- **Last 30 days**: 1-hour intervals

**Response:**

```json
{
"server_id": "srv_d1dc36d8",
"start_time": "2026-02-17T18:00:00Z",
"end_time": "2026-02-17T19:00:00Z",
"granularity": "1m",
"data_points": [
{
"timestamp": "2026-02-17T18:00:00Z",
"cpu_avg": 3.31,
"cpu_max": 3.35,
"cpu_min": 3.28,
"memory_avg": 38.35,
"memory_max": 38.85,
"memory_min": 37.84,
"disk_avg": 68,
"disk_max": 68,
"network_avg": 1.24,
"network_max": 5.67,
"temp_avg": 58.89,
"temp_max": 72.87,
"load_avg": 2.12,
"load_max": 2.38,
"sample_count": 60
}
],
"total_points": 61,
"network_details": {
"interfaces": [
{
"name": "enp111s0",
"status": "up",
"rx_bytes": 1674887389,
"tx_bytes": 148772743,
"rx_speed_mbps": 0.024,
"tx_speed_mbps": 0.023
}
],
"total_rx_mbps": 0.095,
"total_tx_mbps": 0.183
},
"disk_details": {
"disks": [
{
"path": "/",
"free_gb": 171,
"used_gb": 354,
"total_gb": 553,
"filesystem": "/dev/nvme0n1p2",
"used_percent": 68
}
]
},
"temperature_details": {
"cpu_temperature": 72.87,
"gpu_temperature": 49,
"system_temperature": 0,
"storage_temperatures": {},
"highest_temperature": 72.87,
"temperature_unit": "celsius"
}
}
```

**Usage Examples:**

```bash
# Realtime (1 hour)
curl "http://localhost:8080/api/servers/srv_d1dc36d8/metrics/tiered?start=2026-02-17T18:00:00Z&end=2026-02-17T19:00:00Z"

# Historical (24 hours)
curl "http://localhost:8080/api/servers/srv_d1dc36d8/metrics/tiered?start=2026-02-16T19:00:00Z&end=2026-02-17T19:00:00Z"

# Historical (7 days)
curl "http://localhost:8080/api/servers/srv_d1dc36d8/metrics/tiered?start=2026-02-10T19:00:00Z&end=2026-02-17T19:00:00Z"
```

**Note:** If the requested time period has no data, the API returns the latest available metrics with a `message` field.

---

### 🔓 Server Sources Management

**Add Source:** `POST /api/servers/{server_id}/sources`

```json
{
"source": "TGBot" // or "Web"
}
```

**Get Sources:** `GET /api/servers/{server_id}/sources`

**Remove Source:** `DELETE /api/servers/{server_id}/sources/{source}`

---

### � Static Server Information

**Endpoint:** `POST/PUT /api/servers/{server_id}/static-info`

Update static/persistent server information (hardware, system details).

**Request:**

```json
{
"server_info": {
"hostname": "gospodin-A620M-Pro-RS",
"os": "Ubuntu",
"os_version": "25.10",
"kernel": "6.17.0-14-generic",
"architecture": "x86_64"
},
"hardware_info": {
"cpu_model": "AMD Ryzen 5 5600X",
"cpu_cores": 6,
"cpu_threads": 12,
"cpu_frequency_mhz": 3700,
"gpu_model": "NVIDIA GeForce RTX 3080",
"gpu_driver": "550.120",
"gpu_memory_gb": 10,
"total_memory_gb": 32,
"motherboard": "ASRock A620M Pro RS",
"bios_version": "1.20"
},
"network_interfaces": [
{
"interface_name": "eth0",
"mac_address": "00:11:22:33:44:55",
"interface_type": "ethernet",
"speed_mbps": 1000,
"vendor": "Realtek",
"driver": "r8169",
"is_physical": true
}
],
"disk_info": [
{
"device_name": "/dev/nvme0n1",
"model": "Samsung 980 PRO",
"serial_number": "S5GXNX0T123456",
"size_gb": 1000,
"disk_type": "nvme",
"interface_type": "nvme",
"filesystem": "ext4",
"mount_point": "/",
"is_system_disk": true
}
]
}
```

**Response:**

```json
{
"message": "Static information updated successfully",
"server_id": "srv_d1dc36d8"
}
```

**Get Static Info:** `GET /api/servers/{server_id}/static-info`

**Get Hardware Only:** `GET /api/servers/{server_id}/static-info/hardware`

**Get Network Interfaces:** `GET /api/servers/{server_id}/static-info/network`

**Get Disk Info:** `GET /api/servers/{server_id}/static-info/disks`

---

### �🔐 API Key Management

**Create Key:** `POST /api/admin/keys`

```json
{
"service_id": "csharp-backend",
"service_name": "C# Web Backend",
"permissions": ["metrics:read", "servers:read"],
"expires_days": 365
}
```

**List Keys:** `GET /api/admin/keys`

**Get Key Details:** `GET /api/admin/keys/{keyId}`

**Revoke Key:** `DELETE /api/admin/keys/{keyId}`

---

### 🔒 Server Management (Bearer Token Required)

**List All Servers:** `GET /api/servers`

**Get Server Status:** `GET /api/servers/{server_id}/status`

## Quick Start

1. **Register a server:**
```bash
curl -X POST http://localhost:8080/RegisterKey \
-H "Content-Type: application/json" \
-d '{"hostname": "my-server", "operating_system": "Ubuntu 22.04"}'
```

2. **Get metrics:**
```bash
curl "http://localhost:8080/api/servers/YOUR_SERVER_ID/metrics/tiered?start=$(date -d '1 hour ago' -Iseconds)&end=$(date -Iseconds)"
```

3. **Use API key for backend integration:**
```bash
curl "http://localhost:8080/api/servers/YOUR_SERVER_ID/metrics/tiered?start=2026-02-17T18:00:00Z&end=2026-02-17T19:00:00Z" \
-H "X-API-Key: sk_csharp_backend_development_key_change_in_production"
```

## Performance

- **Response time:** <40ms for complex queries
- **Auto-granularity:** Optimized based on time range
- **Data retention:** 90 days (configurable)
- **Max time range:** 30 days per request

## Error Codes

- `400` - Bad Request (missing/invalid parameters)
- `401` - Unauthorized (invalid/missing credentials)
- `404` - Not Found (server doesn't exist)
- `500` - Internal Server Error
[![Go Report Card](https://goreportcard.com/badge/github.com/godofphonk/ServerEyeAPI)](https://goreportcard.com/report/github.com/godofphonk/ServerEyeAPI)
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This README appears to have been truncated to only the Go Report Card badge, removing all project documentation. If this wasn't intentional, restore the previous contents or replace with a concise new README that still documents setup, auth, and key endpoints.

Copilot uses AI. Check for mistakes.
Loading
Loading