Como crear una prueba sintetica gratis usando Rust y Cloudflare
Introducción
En este artículo, vamos a explorar cómo crear y usar un chequeo sintético muy simple. Si no sabés qué es eso, básicamente significa:
Un chequeo sintético es una prueba proactiva que simula interacciones de usuario o solicitudes de red para monitorear el rendimiento y la disponibilidad de los servicios. Los chequeos sintéticos también se conocen como pruebas sintéticas o monitoreo sintético.
Si querés probarlo, podés forkear el repositorio acá.
Un par de cosas: Cloudflare tiene algunas limitaciones en los workers y también en el nivel gratuito, así que si te encontrás con problemas, asegurate de revisar la documentación. En este ejemplo, solo estoy haciendo un chequeo y gestionando una acción. Si necesitás tener en cuenta más escenarios, podés crear algún tipo de enrutador en la función scheduled
(que es la que vamos a usar, ya que será ejecutada por un CRON definido).
Código
Primero, vamos a chusmear el código para ver cómo es y declarar qué vamos a probar y qué pasa en caso de fallo… este archivo se llama lib.rs
:
use serde_json::json;
use std::sync::atomic::{AtomicU32, Ordering};
use worker::*;
static FAILED_CHECKS: AtomicU32 = AtomicU32::new(0);
const MAX_FAILURES: u32 = 3;
#[event(scheduled)]
pub async fn scheduled(_event: ScheduledEvent, env: Env, _ctx: ScheduleContext) {
// Crea una solicitud fetch a nuestro endpoint de salud
let url = env
.var("HEALTH_CHECK_URL")
.expect("HEALTH_CHECK_URL debe estar configurada")
.to_string();
let req = Request::new_with_init(&url, RequestInit::new().with_method(Method::Get))
.expect("No se pudo crear la solicitud");
match Fetch::Request(req).send().await {
Ok(resp) => {
if resp.status_code() == 200 {
// Reinicia el contador en caso de chequeo exitoso
console_log!("Chequeo de salud exitoso para {}! 🎉", url);
FAILED_CHECKS.store(0, Ordering::SeqCst);
} else {
console_log!(
"Chequeo de salud falló con código de estado: {}, para: {}",
resp.status_code(),
url
);
handle_failed_check(&env).await;
}
}
Err(e) => {
console_log!("Chequeo de salud falló con error: {:?}, para: {}", e, url);
handle_failed_check(&env).await;
}
}
}
async fn handle_failed_check(env: &Env) {
let url = env
.var("HEALTH_CHECK_URL")
.expect("HEALTH_CHECK_URL debe estar configurada")
.to_string();
let current_failures = FAILED_CHECKS.fetch_add(1, Ordering::SeqCst) + 1;
console_log!(
"Chequeo de salud falló {} veces para {} 😓",
current_failures,
url
);
if current_failures >= MAX_FAILURES {
console_log!("Enviando notificación a Slack 🚨");
if let Ok(webhook_url) = env.var("SLACK_WEBHOOK_URL") {
let message = json!({
"text": format!("🚨 Chequeo de salud falló {} veces seguidas para el servicio {}! Por favor, revisá el servicio.", current_failures, url)
});
let req = Request::new_with_init(
webhook_url.to_string().as_str(),
RequestInit::new()
.with_method(Method::Post)
.with_body(Some(serde_json::to_string(&message).unwrap().into())),
)
.expect("No se pudo crear la solicitud webhook");
match Fetch::Request(req).send().await {
Ok(_) => console_log!("Notificación de Slack enviada con éxito"),
Err(e) => console_log!("No se pudo enviar la notificación de Slack: {:?}", e),
}
} else {
console_log!("SLACK_WEBHOOK_URL no configurada!");
}
// Reinicia el contador después de la notificación
FAILED_CHECKS.store(0, Ordering::SeqCst);
}
}
NOTA: necesitás configurar estas dos variables de entorno, una se define a través de wrangler y el secreto se puede crear con el siguiente comando:
npx wrangler secret put SLACK_WEBHOOK_URL
En simples pasos:
- Chequea la URL provista en la variable de entorno: HEALTH_CHECK_URL
- Reintenta 3 veces - Envía una notificación a Slack
Desplegándolo
Si queremos desplegarlo manualmente, podemos hacerlo ejecutando:
❯ npx wrangler deploy
⛅️ wrangler 3.101.0
--------------------
Running custom build: cargo install -q worker-build && worker-build --release
[INFO]: 🎯 Buscando el objetivo Wasm...
[INFO]: 🌀 Compilando a Wasm...
Finished `release` profile [optimized] target(s) in 0.04s
[INFO]: ⬇️ Instalando wasm-bindgen...
[INFO]: Campos opcionales faltantes en Cargo.toml: 'description', 'repository' y 'license'. No son necesarios, pero recomendados
[INFO]: ✨ Listo en 0.25s
[INFO]: 📦 Tu paquete wasm está listo para publicar en ~/Webs/healthcheck/build.
shim.mjs 16.3kb
⚡ Listo en 4ms
Total Upload: 439.09 KiB / gzip: 159.83 KiB
Worker Startup Time: 1 ms
Tu worker tiene acceso a los siguientes bindings:
- Vars:
- HEALTH_CHECK_URL: "[https://redbeard.team/en/blog](https://redbeard.team/en/blog)"
Subido healthcheck (4.00 sec)
Desplegados los disparadores de healthcheck (0.41 sec)
schedule: */2 * * * *
Current Version ID: 7030ba06-1be0-4376-9ced-0c9ba6ef2abc
Alternativamente, podemos dejar que Github Action lo despliegue automáticamente por nosotros. Cloudflare tiene un sistema de CI/CD, pero todavía no soporta Rust ni sudo, así que no podés instalar paquetes para construir y lanzar desde ahí. Para esto, solo necesitás dos variables de entorno en tus secretos, como verás en la action (usá la plantilla para workers al crear la key).
name: Desplegar Worker
on:
push:
branches:
- master
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
name: Desplegar
steps:
- uses: actions/checkout@v4
- name: Configurar Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: wasm32-unknown-unknown
override: true
profile: minimal
- name: Instalar wrangler
run: npm install -g wrangler
- name: Construir y Desplegar
run: |
cargo install -q worker-build
worker-build --release
wrangler deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
Y por último, pero no menos importante, la configuración de Wrangler (wrangler.toml
):
name = "healthcheck"
main = "build/worker/shim.mjs"
compatibility_date = "2025-01-12"
workers_dev = false
preview_urls = false
[build]
command = "cargo install -q worker-build && worker-build --release"
[triggers]
crons = ["*/2 * * * *"]
[vars]
HEALTH_CHECK_URL = "[https://redbeard.team/en/blog](https://redbeard.team/en/blog)"
[observability]
enabled = true
head_sampling_rate = 1
El resultado
Los logs deberían verse algo así:
Y cuando las cosas no van bien, deberías recibir un mensaje de Slack donde sea que hayas configurado el webhook.
¡Espero que te haya gustado y te sea útil! ¡Hasta la próxima!
No tienes cuenta? Regístrate aqui
Ya registrado? Iniciar sesión a tu cuenta ahora.
-
Comentarios
Online: 0
Por favor inicie sesión para poder escribir comentarios.