Migrer depuis UptimeRobot
Recopiez vos monitors UptimeRobot dans OKStatus en une commande, faites tourner les deux outils en parallèle quelques jours, puis basculez. Votre compte UptimeRobot n’est jamais modifié.
Ce que fait ce tutoriel
Section intitulée « Ce que fait ce tutoriel »Un script Python lit vos monitors avec l’API d’UptimeRobot et les recrée avec l’API d’OKStatus. Il n’utilise que la bibliothèque standard : rien à installer.
Avant de commencer
Section intitulée « Avant de commencer »- Une clé UptimeRobot en lecture seule : Integrations → API → Read-only API key. Elle ne peut rien modifier.
- Une clé OKStatus Complète, sur l’offre Max (Paramètres → Clés API). Sur Free ou Pro, l’essai à blanc de l’étape 3 vous donne quand même la liste exacte à recréer à la main.
- Python 3.9 ou plus récent.
1. La correspondance
Section intitulée « 1. La correspondance »| UptimeRobot | OKStatus | Détail |
|---|---|---|
| HTTP(s) | HTTP | même URL, même méthode |
| Keyword | HTTP + mot-clé | « n’existe pas » devient keywordInvert |
| Ping | Ping | |
| Port | TCP | HTTP 80, HTTPS 443, FTP 21, SMTP 25, POP3 110, IMAP 143 ou votre port personnalisé |
| Heartbeat | Heartbeat (push) | une nouvelle URL de ping pour vos tâches cron ; les périodes de plus d’un jour sont ignorées |
| En pause | En pause | le monitor est créé, puis mis en pause |
| Intervalle | Intervalle | relevé au minimum de votre offre si besoin, un jour au plus |
2. Le script
Section intitulée « 2. Le script »Téléchargez uptimerobot_to_okstatus.py, ou copiez-le. Ses messages sont en anglais.
#!/usr/bin/env python3"""Copy UptimeRobot monitors to OKStatus.
Reads your monitors with UptimeRobot's API (v2, read-only key is enough) andcreates them in OKStatus with its REST API (Full key, Max plan). Without--apply it only prints what it would create. Your UptimeRobot account isnever changed. Python 3.9+, standard library only.
export UPTIMEROBOT_API_KEY=ur... export OKSTATUS_REGIONS=fr-dc3,de-fra,nl-ams # regions of your plan export OKSTATUS_MIN_INTERVAL=30 # 300 Free, 60 Pro, 30 Max python3 uptimerobot_to_okstatus.py # dry run export OKSTATUS_API_KEY=oks_live_... python3 uptimerobot_to_okstatus.py --apply
Guide: https://okstatus.eu/docs/tutorials/migrate-from-uptimerobot/"""import jsonimport osimport reimport sysimport urllib.errorimport urllib.parseimport urllib.request
UR_API = os.environ.get("UPTIMEROBOT_API_URL", "https://api.uptimerobot.com/v2")OK_API = os.environ.get("OKSTATUS_API_URL", "https://api.okstatus.eu/api/v1")REGIONS = [r.strip() for r in os.environ.get("OKSTATUS_REGIONS", "fr-dc3,de-fra").split(",") if r.strip()]MIN_INTERVAL = int(os.environ.get("OKSTATUS_MIN_INTERVAL", "60"))APPLY = "--apply" in sys.argv
# UptimeRobot v2 codes (uptimerobot.com/api/legacy)PORTS = {1: 80, 2: 443, 3: 21, 4: 25, 5: 110, 6: 143} # port monitor sub_typeMETHODS = {1: "HEAD", 2: "GET", 3: "POST", 4: "PUT", 5: "PATCH", 6: "DELETE", 7: "OPTIONS"}PAUSED = 0 # monitor status
def uptimerobot_monitors(): key = os.environ.get("UPTIMEROBOT_API_KEY") if not key: sys.exit("Set UPTIMEROBOT_API_KEY (Integrations → API → read-only key).") offset = 0 while True: form = {"api_key": key, "format": "json", "offset": offset, "limit": 50, "http_request_details": "true"} req = urllib.request.Request(f"{UR_API}/getMonitors", urllib.parse.urlencode(form).encode()) with urllib.request.urlopen(req, timeout=30) as r: page = json.load(r) if page.get("stat") != "ok": sys.exit(f"UptimeRobot: {page.get('error')}") yield from page.get("monitors", []) offset += 50 if offset >= int(page.get("pagination", {}).get("total", 0)): return
def as_int(value, default=0): try: return int(value) except (TypeError, ValueError): return default
def convert(m): """(body of POST /api/v1/monitors, None) or (None, why it is skipped).""" kind = as_int(m.get("type")) body = { "name": str(m.get("friendly_name") or m.get("url") or "Monitor")[:100], "regions": REGIONS, # OKStatus accepts 30 s to 1 day, and never less than the plan's floor. "interval": min(max(as_int(m.get("interval"), 300), MIN_INTERVAL), 86400), } if kind in (1, 2): # HTTP(s), Keyword body.update(type="http", url=m["url"]) method = METHODS.get(as_int(m.get("http_method"), 2), "GET") if method != "GET": body["httpMethod"] = method if kind == 2: body["keyword"] = m.get("keyword_value") or "" body["keywordInvert"] = as_int(m.get("keyword_type")) == 2 # 2 = "not exists" elif kind == 3: # Ping body.update(type="ping", url=m["url"]) elif kind == 4: # Port sub = as_int(m.get("sub_type")) port = as_int(m.get("port")) if sub == 99 else PORTS.get(sub) if not port: return None, "port monitor without a port" body.update(type="tcp", url=m["url"], port=port) elif kind == 5: # Heartbeat if as_int(m.get("interval")) > 86400: # A shorter period would report the job down between two runs. return None, "heartbeat period over one day, the OKStatus maximum" slug = re.sub(r"[^a-z0-9]+", "-", body["name"].lower()).strip("-") body.update(type="push", url=slug or "heartbeat") else: return None, f"UptimeRobot type {m.get('type')} has no equivalent" return body, None
def okstatus(method, url, body): req = urllib.request.Request(url, json.dumps(body).encode(), method=method, headers={ "Authorization": f"Bearer {os.environ['OKSTATUS_API_KEY']}", "Content-Type": "application/json", }) with urllib.request.urlopen(req, timeout=30) as r: return json.load(r)["data"]
def main(): if APPLY and not os.environ.get("OKSTATUS_API_KEY"): sys.exit("Set OKSTATUS_API_KEY (a Full key, Settings → API Keys) to use --apply.") created = skipped = failed = 0 for m in uptimerobot_monitors(): name = m.get("friendly_name", "?") body, why = convert(m) if body is None: print(f"SKIPPED {name} ({why})") skipped += 1 continue paused = as_int(m.get("status"), -1) == PAUSED if not APPLY: print(f"TO CREATE {body['type']:5} {body['name']} -> {body['url']}" + (" (paused)" if paused else "")) continue try: new = okstatus("POST", f"{OK_API}/monitors", body) if paused: okstatus("PATCH", f"{OK_API}/monitors/{new['id']}", {"status": "paused"}) extra = f" · new ping URL: {new['pushUrl']}" if body["type"] == "push" else "" print(f"CREATED {body['name']}{extra}") created += 1 except urllib.error.HTTPError as e: print(f"FAILED {body['name']}: {e.code} {e.read().decode(errors='replace')[:200]}") failed += 1 if APPLY: print(f"\n{created} created, {skipped} skipped, {failed} failed.") if failed: sys.exit(1) else: print("\nDry run: nothing created. Add --apply to create these monitors.")
if __name__ == "__main__": main()3. Un essai à blanc
Section intitulée « 3. Un essai à blanc »export UPTIMEROBOT_API_KEY=ur…export OKSTATUS_REGIONS=fr-dc3,de-fra,nl-ams # regions of your planexport OKSTATUS_MIN_INTERVAL=30 # 300 on Free, 60 on Pro, 30 on Maxpython3 uptimerobot_to_okstatus.pyTO CREATE http Website -> https://example.comTO CREATE http API health -> https://api.example.com/healthTO CREATE tcp SMTP -> mail.example.comTO CREATE push Nightly backup -> nightly-backupTO CREATE ping Office router -> 203.0.113.10 (paused)
Dry run: nothing created. Add --apply to create these monitors.Rien n’est créé sans --apply. Relisez la liste, ajustez les variables, recommencez autant que nécessaire.
4. La migration
Section intitulée « 4. La migration »export OKSTATUS_API_KEY=oks_live_…python3 uptimerobot_to_okstatus.py --applyCREATED WebsiteCREATED API healthCREATED SMTPCREATED Nightly backup · new ping URL: https://backend.okstatus.eu/push/…CREATED Office router
5 created, 0 skipped, 0 failed.5. Après la migration
Section intitulée « 5. Après la migration »- Recréez vos canaux d’alerte dans le tableau de bord, puis rattachez-les aux monitors ou à un groupe. Le script ne les copie pas : ils contiennent des secrets.
- Remplacez l’URL de ping de chaque heartbeat dans vos tâches cron. Gardez le même appel :
GET,POSTetHEADcomptent tous comme un ping. Voir Heartbeat. - Faites tourner les deux outils une semaine et comparez les alertes. Avec plusieurs régions, OKStatus n’alerte que si la majorité confirme : attendez-vous à moins d’alertes isolées.
- Recréez votre page de statut et pointez votre domaine (CNAME) vers OKStatus. Voir Pages de statut.
- Mettez en pause les monitors UptimeRobot, puis fermez le compte quand vous êtes prêt.
Ce qui n’est pas migré
Section intitulée « Ce qui n’est pas migré »- l’historique de disponibilité : OKStatus commence à compter le jour de la migration ;
- les canaux d’alerte, les pages de statut et les maintenances ;
- les identifiants, en-têtes et corps de requête des monitors HTTP : ajoutez-les dans le tableau de bord ;
- les types sans équivalent (UDP, services tiers) et les heartbeats de plus d’un jour : le script les liste comme ignorés (
SKIPPED).