feat(monitor): integração Beszel/Stack Observer, tickets do observer e novos sites no uptime
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Stack Observer API Route
|
||||
* GET /api/stack-observer - Get divergence data from observer.db
|
||||
* Provides real-time automation liveness metrics (result_real divergences)
|
||||
* @author Descomplicar® | @link descomplicar.pt | @copyright 2026
|
||||
*/
|
||||
import { Router } from 'express'
|
||||
import type { Request, Response } from 'express'
|
||||
import * as observerService from '../services/observer.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
/**
|
||||
* Get divergence data
|
||||
* Returns evaluations with result_real != result_nominal (automation failures/liveness violations)
|
||||
*/
|
||||
router.get('/', async (_req: Request, res: Response) => {
|
||||
try {
|
||||
const data = await observerService.getDivergences()
|
||||
res.json(data)
|
||||
} catch (error: unknown) {
|
||||
console.error('Stack Observer API error:', error)
|
||||
const message = error instanceof Error ? error.message : 'Internal server error'
|
||||
res.status(500).json({ error: message })
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Get single divergence by ID
|
||||
* Returns full evaluation record with context
|
||||
*/
|
||||
router.get('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { id } = req.params
|
||||
if (!id || typeof id !== 'string') {
|
||||
res.status(400).json({ error: 'Invalid divergence ID' })
|
||||
return
|
||||
}
|
||||
const data = await observerService.getDivergenceById(id)
|
||||
if (!data) {
|
||||
res.status(404).json({ error: 'Divergence not found' })
|
||||
return
|
||||
}
|
||||
res.json(data)
|
||||
} catch (error: unknown) {
|
||||
console.error('Stack Observer detail error:', error)
|
||||
const message = error instanceof Error ? error.message : 'Internal server error'
|
||||
res.status(500).json({ error: message })
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of automations (from hermes_jobs)
|
||||
* F1b: Colector ingesta jobs do Hermes
|
||||
*/
|
||||
router.get('/automations', async (_req: Request, res: Response) => {
|
||||
try {
|
||||
const data = await observerService.getAutomations()
|
||||
res.json(data)
|
||||
} catch (error: unknown) {
|
||||
console.error('Get automations error:', error)
|
||||
const message = error instanceof Error ? error.message : 'Internal server error'
|
||||
res.status(500).json({ error: message })
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Get list of gate events
|
||||
* F1a: Colector ingesta gate_events da fila
|
||||
*/
|
||||
router.get('/gate-events', async (_req: Request, res: Response) => {
|
||||
try {
|
||||
const data = await observerService.getGateEvents()
|
||||
res.json(data)
|
||||
} catch (error: unknown) {
|
||||
console.error('Get gate events error:', error)
|
||||
const message = error instanceof Error ? error.message : 'Internal server error'
|
||||
res.status(500).json({ error: message })
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
Reference in New Issue
Block a user