Uptime · Logs · On-call · Heartbeats · Status Page | Generado por CULTIVA IA · 16 Jun 2026
# NutriFlow — Configuración Better Stack via Terraform # Proveedor: BetterStackHQ/better-uptime terraform { required_providers { betteruptime = { source = "BetterStackHQ/better-uptime" version = "~> 0.5" } } } # ── Política de escalado ──────────────────────────────────── resource "betteruptime_escalation_policy" "default" { name = "NutriFlow Producción" repeat = 3 steps = [ { type = "notify_on_call", wait_before = 0 }, { type = "call_on_call", wait_before = 5 }, { type = "notify_team", wait_before = 10 }, { type = "notify_all", wait_before = 15 } ] } # ── Monitor API REST ──────────────────────────────────────── resource "betteruptime_monitor" "api" { url = "https://api.nutriflow.app/health" monitor_type = "status" check_frequency = 30 regions = ["us", "eu", "asia"] confirmation_period = 2 # 2 fallos consecutivos antes de alertar request_headers = [{ name = "x-health-token" value = "${var.health_check_token}" }] expected_status_codes = [200] policy_id = betteruptime_escalation_policy.default.id } # ── Monitor DB TCP ────────────────────────────────────────── resource "betteruptime_monitor" "database" { url = "tcp://db.nutriflow.internal:5432" monitor_type = "tcp" check_frequency = 60 policy_id = betteruptime_escalation_policy.default.id } # ── Monitor SSL ───────────────────────────────────────────── resource "betteruptime_monitor" "ssl" { url = "https://nutriflow.app" monitor_type = "ssl" ssl_expiration = 30 # alerta 30 días antes de expirar policy_id = betteruptime_escalation_policy.default.id } # ── Heartbeat cron semanal ────────────────────────────────── resource "betteruptime_heartbeat" "weekly_report" { name = "Reporte Semanal NutriFlow" period = 10080 # 7 días en minutos grace = 30 # 30 min de gracia policy_id = betteruptime_escalation_policy.default.id }
import pino from "pino"; // Logger global NutriFlow con transporte Logtail export const logger = pino( pino.transport({ target: "@logtail/pino", options: { sourceToken: process.env.LOGTAIL_SOURCE_TOKEN, }, }) ); // Ejemplo: expediente médico sincronizado logger.info({ event: "expediente.sync", pacienteId: "pac_es_00421", clinicaId: "cli_madrid_07", campos_actualizados: ["peso", "imc", "plan_semana"], duration_ms: 84, }, "Expediente sincronizado OK"); // Error de facturación con contexto completo logger.error({ event: "facturacion.error", clinicaId: "cli_barcelona_03", plan: "pro_anual", stripe_error: "card_declined", retryable: true, intento: 2, }, "Pago rechazado");
// Cron semanal con heartbeat — NutriFlow async function weeklyClinicReport() { try { const clinicas = await db.getActiveClinics(); for (const clinica of clinicas) { const report = await generateWeeklyReport(clinica); await emailService.send({ to: clinica.adminEmail, subject: `Resumen semanal — ${clinica.nombre}`, pdf: report.pdfBuffer, }); } // ✓ Éxito — notificar a Better Stack await fetch( "https://uptime.betterstack.com/api/v1/heartbeat/" + process.env.HEARTBEAT_WEEKLY_TOKEN ); logger.info({ clinicas_procesadas: clinicas.length, }, "Reporte semanal enviado OK"); } catch (err) { // ✗ Sin ping → Better Stack alerta al on-call logger.error({ err }, "Fallo en reporte semanal"); } }
// Crear incidente programático en Better Stack // (e.g. detectado por job de monitoreo interno) export async function createIncident( name: string, summary: string ) { const res = await fetch( "https://uptime.betterstack.com/api/v2/incidents", { method: "POST", headers: { Authorization: `Bearer ${process.env.BETTERSTACK_API_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ requester_email: "ops@nutriflow.app", name, summary, status_page_ids: [ process.env.BETTERSTACK_STATUS_PAGE_ID ], }), } ); return res.json(); } // Uso: latencia elevada detectada internamente await createIncident( "Latencia elevada en /analisis", "Tiempos de respuesta > 1s en endpoint de análisis nutricional. " + "Investigando causa. Sin pérdida de datos." );