Documentation PulseRadar
Observabilité complète pour vos serveurs — logs, métriques, APM, error tracking et traces distribuées, hébergé en France.
Démarrage rapide
Connectez votre premier serveur en moins de 2 minutes.
1. Créez une clé API
Rendez-vous dans Dashboard → Clés API, cliquez sur Nouvelle clé. Copiez la clé affichée — elle ne sera plus visible ensuite.
2. Installez l'agent
Sur votre serveur Linux, lancez en root :
curl -sSL https://pulseradar.cloud/install | bash -s -- --api-key <VOTRE_CLÉ>
L'agent détecte automatiquement les services actifs (Nginx, MySQL, PHP-FPM…) et configure Fluent Bit pour les surveiller.
3. Vérifiez dans le dashboard
Votre serveur apparaît dans Dashboard → Serveurs avec un point vert dans les 30 secondes. Les logs et métriques arrivent en temps réel.
Agent & installation
L'agent PulseRadar est un binaire Go léger (~10 Mo) qui collecte les métriques système et orchestre Fluent Bit pour la collecte des logs applicatifs.
Installation Linux
# Installation automatique (recommandée) curl -sSL https://pulseradar.cloud/install | bash -s -- --api-key <CLÉ> # Options disponibles --api-key <CLÉ> Clé API (obligatoire) --server-name <NOM> Nom affiché dans le dashboard (défaut: hostname)
Installation Windows
# PowerShell en administrateur
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
iex (New-Object Net.WebClient).DownloadString('https://pulseradar.cloud/install.ps1')Ce que fait l'agent
| Fonction | Fréquence | Détail |
|---|---|---|
| Métriques système | Toutes les 10s | CPU, RAM, swap, disk I/O, réseau |
| Heartbeat | Toutes les 30s | Statut online/offline dans le dashboard |
| Logs applicatifs | Temps réel | Via Fluent Bit (tail des fichiers log) |
| Mise à jour auto | Au démarrage | Vérifie et télécharge les nouvelles versions |
Gestion du service
# Statut sudo systemctl status pulseradar-agent # Redémarrage sudo systemctl restart pulseradar-agent # Logs de l'agent sudo journalctl -u pulseradar-agent -f
Fichiers de configuration
/etc/pulseradar/agent.conf Configuration de l'agent /etc/fluent-bit/fluent-bit.conf Configuration Fluent Bit (auto-généré) /etc/fluent-bit/parsers.conf Parseurs de logs
/etc/pulseradar/agent.conf.Ingestion de logs
PulseRadar accepte les logs via HTTP JSON. Chaque événement est normalisé et stocké dans ClickHouse.
Format d'un événement
{
"level": "error", // fatal|critical|error|warning|info|debug
"message": "Connection refused to database",
"source": "mon-app", // identifiant libre de la source
"timestamp": "2026-03-30T14:00:00Z", // optionnel, défaut: maintenant
"host": "web01", // optionnel
"fields": { // données structurées libres
"user_id": "42",
"duration_ms": "320"
}
}Envoyer un log
# Log unique
curl -X POST https://ingest.pulseradar.cloud/v1/logs \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"level":"error","message":"Oops","source":"mon-app"}'
# Batch (jusqu'à 500 événements par requête)
curl -X POST https://ingest.pulseradar.cloud/v1/logs \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '[{"level":"info","message":"Start"},{"level":"error","message":"Fail"}]'Niveaux de log
| Niveau | Alias acceptés | Couleur dashboard |
|---|---|---|
| critical | fatal | Rouge vif |
| error | err, exception | Rouge |
| warning | warn | Orange |
| info | — | Bleu |
| debug | trace | Gris |
info et debug sont filtrés par défaut pour économiser le quota. Activez Conserver les logs info dans les paramètres du projet pour les stocker.SDKs officiels
Envoyez des logs directement depuis votre code applicatif, sans agent. Tous les SDKs sont disponibles en téléchargement sur pulseradar.cloud/sdk.
Concepts communs à tous les SDKs
| Paramètre | Requis | Description |
|---|---|---|
| api_key | Oui | Clé API (pr_xxx). Variable d'env recommandée : PULSERADAR_API_KEY |
| source | Recommandé | Identifiant de votre app (ex: mon-api, frontend, worker) |
| server_id | Optionnel | UUID du serveur — lie les logs au serveur dans le dashboard. Récupérez-le depuis /etc/pulseradar/agent.conf ou GET /api/servers |
| endpoint | Non | URL d'ingestion (défaut: https://ingest.pulseradar.cloud/v1/logs) |
Niveaux de log
| Niveau | Méthode | Facturé |
|---|---|---|
| critical | .critical() | Toujours |
| error | .error() | Toujours |
| warning | .warning() | Toujours |
| info | .info() | Seulement si keep_info activé |
| debug | .debug() | Seulement si keep_info activé |
Fonctionnalités communes
Tous les SDKs supportent :
- Batch queue — les logs sont groupés et envoyés toutes les 5s ou tous les 50 logs
- captureException — capture une exception avec stack trace (5 frames max)
- Fields / metadata — données structurées libres (user_id, request_id, etc.)
- Flush / Close — vide la queue manuellement (important pour les scripts courts)
- Header X-Server-Id — envoyé automatiquement si server_id est configuré
flush() ou close() avant la fin de votre programme (scripts CLI, Lambda, cron jobs), sinon les derniers logs en queue seront perdus.Node.js
# Télécharger curl -O https://pulseradar.cloud/sdk/nodejs/index.js
const PulseRadar = require('./index.js') // ou le chemin vers le fichier
const logger = new PulseRadar({
apiKey: process.env.PULSERADAR_API_KEY,
serverId: process.env.PULSERADAR_SERVER_ID, // optionnel
source: 'mon-api',
})
// Logs avec fields
logger.info('Serveur démarré', { port: '3000', env: 'production' })
logger.error('Erreur DB', { query: 'SELECT ...', duration_ms: '320' })
// Capture d'exception avec stack trace
try {
riskyOperation()
} catch (err) {
logger.captureException(err, { user_id: '42', route: '/api/users' })
}
// Express middleware — capture globale des erreurs
app.use((err, req, res, next) => {
logger.captureException(err, { path: req.path, method: req.method })
res.status(500).json({ error: 'Internal error' })
})
// IMPORTANT : flush avant exit (scripts, Lambda)
process.on('beforeExit', () => logger.flush())Python
# Télécharger mkdir -p pulseradar curl -o pulseradar/__init__.py https://pulseradar.cloud/sdk/python/pulseradar/__init__.py
from pulseradar import PulseRadar
import os
logger = PulseRadar(
api_key=os.environ["PULSERADAR_API_KEY"],
server_id=os.environ.get("PULSERADAR_SERVER_ID"),
source="mon-api",
)
# Logs avec fields (kwargs)
logger.info("Démarrage", version="1.0", port="8000")
logger.error("Erreur DB", query="SELECT ...", duration_ms="320")
# Capture d'exception (utilise sys.exc_info si pas d'argument)
try:
risky()
except Exception:
logger.capture_exception(user_id="42")
# Django middleware
class PulseRadarMiddleware:
def process_exception(self, request, exception):
logger.capture_exception(exception, path=request.path)
# Flask error handler
@app.errorhandler(Exception)
def handle_error(e):
logger.capture_exception(e)
return "Error", 500
# IMPORTANT : flush en fin de script
import atexit
atexit.register(logger.flush)PHP
# Télécharger curl -O https://pulseradar.cloud/sdk/php/src/PulseRadar.php
require_once __DIR__ . '/PulseRadar.php';
use PulseRadar\PulseRadar;
$logger = new PulseRadar([
'api_key' => getenv('PULSERADAR_API_KEY'),
'server_id' => getenv('PULSERADAR_SERVER_ID'),
'source' => 'mon-api',
'async' => true, // batch + flush au __destruct
]);
$logger->info('Démarrage');
$logger->error('Erreur DB', ['query' => 'SELECT ...', 'duration_ms' => '320']);
// Capture d'exception
try {
risky();
} catch (\Throwable $e) {
$logger->captureException($e, ['user_id' => '42']);
}
// Laravel : dans app/Exceptions/Handler.php
public function report(\Throwable $e) {
app(PulseRadar::class)->captureException($e);
parent::report($e);
}Ruby
curl -O https://pulseradar.cloud/sdk/ruby/lib/pulseradar.rb
require_relative 'pulseradar'
logger = PulseRadar::Client.new(
api_key: ENV['PULSERADAR_API_KEY'],
server_id: ENV['PULSERADAR_SERVER_ID'],
source: 'mon-api',
)
logger.info('Démarrage', port: '3000')
logger.error('Erreur DB', query: 'SELECT ...')
# Capture d'exception
begin
risky_operation
rescue => e
logger.capture_exception(e, user_id: '42')
end
# Rails : dans config/initializers/pulseradar.rb
Rails.application.config.middleware.use(proc { |env|
begin
@app.call(env)
rescue => e
PULSERADAR.capture_exception(e, path: env['PATH_INFO'])
raise
end
})Java / Spring Boot
# Télécharger curl -O https://pulseradar.cloud/sdk/java/src/main/java/cloud/pulseradar/PulseRadar.java curl -O https://pulseradar.cloud/sdk/java/src/main/java/cloud/pulseradar/PulseRadarLogbackAppender.java
// Usage direct
PulseRadar logger = new PulseRadar.Builder()
.apiKey(System.getenv("PULSERADAR_API_KEY"))
.serverId(System.getenv("PULSERADAR_SERVER_ID"))
.source("mon-api")
.build();
logger.info("Server started", Map.of("port", "8080"));
logger.error("DB failed", Map.of("query", "SELECT ..."));
try { riskyOperation(); }
catch (Exception e) { logger.captureException(e, Map.of("user_id", "42")); }
// IMPORTANT : flush au shutdown
Runtime.getRuntime().addShutdownHook(new Thread(logger::flush));Ou via Logback appender (zéro code, Spring Boot / tout projet SLF4J) :
<!-- src/main/resources/logback.xml -->
<appender name="PULSERADAR" class="cloud.pulseradar.PulseRadarLogbackAppender">
<apiKey>${PULSERADAR_API_KEY}</apiKey>
<source>mon-api</source>
<serverId>${PULSERADAR_SERVER_ID}</serverId>
</appender>
<root level="WARN">
<appender-ref ref="PULSERADAR" />
</root>log.error("msg", exception) incluent automatiquement la stack trace.Go
# Télécharger mkdir -p pulseradar && cd pulseradar curl -O https://pulseradar.cloud/sdk/go/pulseradar.go curl -O https://pulseradar.cloud/sdk/go/slog.go curl -O https://pulseradar.cloud/sdk/go/go.mod
package main
import (
"log/slog"
"os"
pulseradar "./pulseradar" // chemin local
)
func main() {
client := pulseradar.New(os.Getenv("PULSERADAR_API_KEY"),
pulseradar.WithSource("mon-api"),
pulseradar.WithServerID(os.Getenv("PULSERADAR_SERVER_ID")),
)
defer client.Close() // flush les logs restants
client.Info("Démarrage", pulseradar.F("port", "8080"))
client.Error("Erreur DB", pulseradar.F("query", "SELECT ..."))
if err := riskyOperation(); err != nil {
client.CaptureException(err, pulseradar.F("user_id", "42"))
}
// Intégration log/slog (Go 1.21+)
logger := slog.New(pulseradar.NewSlogHandler(client))
slog.SetDefault(logger)
slog.Info("Hello from slog", "key", "value")
}
// Gin middleware
func PulseRadarMiddleware(client *pulseradar.Client) gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
for _, err := range c.Errors {
client.CaptureException(err.Err, pulseradar.F("path", c.FullPath()))
}
}
}.NET / C#
curl -O https://pulseradar.cloud/sdk/dotnet/PulseRadar/PulseRadar.cs
using PulseRadar;
var logger = new PulseRadarClient(
apiKey: Environment.GetEnvironmentVariable("PULSERADAR_API_KEY")!,
source: "mon-api",
serverId: Environment.GetEnvironmentVariable("PULSERADAR_SERVER_ID")
);
logger.Info("Démarrage", new() { ["port"] = "5000" });
logger.Error("Erreur DB", new() { ["query"] = "SELECT ..." });
try { RiskyOperation(); }
catch (Exception ex) { logger.CaptureException(ex, new() { ["user_id"] = "42" }); }
// ASP.NET Core : dans Program.cs
app.Use(async (context, next) => {
try { await next(); }
catch (Exception ex) {
logger.CaptureException(ex, new() { ["path"] = context.Request.Path });
throw;
}
});
// IMPORTANT : dispose en fin de vie
using var logger = new PulseRadarClient(...);Rust
mkdir -p pulseradar/src && cd pulseradar curl -O https://pulseradar.cloud/sdk/rust/Cargo.toml curl -o src/lib.rs https://pulseradar.cloud/sdk/rust/src/lib.rs
use pulseradar::{Client, Field};
let client = Client::new("pr_your_api_key")
.source("mon-api")
.server_id("optional-server-id");
client.info("Démarrage", &[Field::new("port", "8080")]);
client.error("Erreur DB", &[Field::new("query", "SELECT ...")]);
// Capture d'erreur
client.capture_error(&some_error, &[Field::new("user_id", "42")]);
// Le client flush automatiquement au drop
drop(client);/etc/pulseradar/agent.conf sur le serveur où tourne votre app, ou via GET /api/servers. Cela permet de voir les logs applicatifs dans le dashboard du serveur, corrélés avec les métriques infra.Sources supportées
L'agent configure automatiquement Fluent Bit pour les services détectés.
| Source | Valeur source | Fonctionnalités |
|---|---|---|
| journald | journald | Tous les services systemd (filet universel) |
| auth.log | auth | SSH, sudo, PAM — audit sécurité |
| Nginx | nginx | Logs accès + APM Web + métriques |
| Apache | apache | Logs accès + APM Web + métriques |
| MySQL | mysql | Slow query log + fingerprinting SQL |
| PostgreSQL | postgres | Slow query log + fingerprinting SQL |
| PHP-FPM | php-fpm | Slow log + saturation + stack trace |
| Docker | docker | stdout/stderr des conteneurs |
| Redis | redis | Logs erreur |
| HAProxy | haproxy | Logs accès |
| Syslog | syslog | Logs système kernel/auth |
| RabbitMQ | rabbitmq | Logs erreur, métriques queues/consumers |
| Elasticsearch | elasticsearch | Logs cluster, métriques health/shards/JVM |
| Cron | cron | Jobs planifiés, erreurs silencieuses |
| UFW | ufw | Logs firewall, scans de ports |
| Custom | libre | Via API directe ou Fluent Bit personnalisé |
Ajouter une source personnalisée
Dans /etc/fluent-bit/fluent-bit.conf, ajoutez un bloc INPUT et FILTER :
[INPUT]
Name tail
Path /var/log/mon-app/*.log
Tag mon-app
[FILTER]
Name record_modifier
Match mon-app
Record source mon-app
Record server_id ${SERVER_ID}
Record project_id ${PROJECT_ID}
[OUTPUT]
Name http
Match mon-app
Host ingest.pulseradar.cloud
Port 443
URI /v1/logs/fluent-bit
Format json
Header Authorization Bearer ${API_KEY}Métriques serveur
L'agent collecte les métriques système toutes les 10 secondes et les pousse vers l'API.
Métriques collectées
| Métrique | Unité | Description |
|---|---|---|
| cpu_pct | % | Utilisation CPU (moyenne tous cœurs) |
| mem_pct | % | RAM utilisée / RAM totale |
| swap_pct | % | Swap utilisé / Swap total |
| load1 | float | Load average 1 minute |
| disk_read_bps | bytes/s | Débit lecture disque |
| disk_write_bps | bytes/s | Débit écriture disque |
| net_recv_bps | bytes/s | Bande passante entrante |
| net_sent_bps | bytes/s | Bande passante sortante |
| disk_used_pct | % | Espace disque utilisé |
Visualisation
Accédez aux graphes dans Serveur → Système. Fenêtres disponibles : 1h, 3h, 12h, 24h avec points à la minute.
Vue Corrélation
La page Serveur → Corrélation superpose les métriques système (CPU, RAM) avec les métriques HTTP (req/s, latence P99) pour identifier les saturations liées au trafic.
APM Web (Nginx / Apache)
PulseRadar agrège automatiquement les access logs Nginx et Apache en métriques de performance à la minute, sans modifier votre configuration de logs.
Métriques APM calculées
| Métrique | Description |
|---|---|
| req_count | Nombre de requêtes |
| err_4xx / err_5xx | Erreurs client / serveur |
| avg_ms / p50 / p75 / p99 | Latence (depuis nginx request_time) |
| count_fast / ok / slow | < 500ms / 500ms–2s / > 2s |
| bytes_out | Bande passante sortante |
| top_ips | 5 IPs les plus actives par minute |
Format de log Nginx requis
Ajoutez ce format dans votre nginx.conf pour activer la latence :
log_format pulseradar '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time';
access_log /var/log/nginx/access.log pulseradar;Score de santé
| Score | Condition |
|---|---|
| ✅ Bon | Taux erreur < 1% ET P99 < 500ms |
| ⚠️ Moyen | Taux erreur < 5% OU P99 < 2s |
| 🔴 Dégradé | Taux erreur > 5% OU P99 > 2s |
DB APM (MySQL / PostgreSQL / PHP-FPM)
PulseRadar parse les slow logs de base de données, fingerprinte les requêtes SQL et agrège les statistiques par minute.
MySQL — configuration
# /etc/mysql/mysql.conf.d/mysqld.cnf slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 0.5 # requêtes > 500ms log_queries_not_using_indexes = 1
PostgreSQL — configuration
# /etc/postgresql/*/main/postgresql.conf log_min_duration_statement = 500 # ms — requêtes > 500ms log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
PHP-FPM — configuration
L'agent ajoute automatiquement ces lignes dans le pool PHP-FPM :
slowlog = /var/log/php-fpm-slow.log request_slowlog_timeout = 2s
Métriques DB APM
| Métrique | Description |
|---|---|
| fingerprint | Requête normalisée (littéraux remplacés par ?) |
| call_count | Nombre d'exécutions sur la période |
| avg_ms / max_ms | Durée moyenne / maximale |
| rows_examined | Lignes analysées (MySQL uniquement) |
| rows_sent | Lignes retournées (MySQL uniquement) |
Fingerprinting SQL
Les requêtes sont normalisées pour regrouper les variantes identiques :
Avant : SELECT * FROM users WHERE id = 42 AND status = 'active' Après : SELECT * FROM users WHERE id = ? AND status = ? Avant : SELECT * FROM orders WHERE id IN (1, 2, 3, 4, 5) Après : SELECT * FROM orders WHERE id IN (?)
Error Tracking
PulseRadar regroupe automatiquement les erreurs identiques en groupes d'erreurs, avec compteur de fréquence, détection de régression et stack trace colorée.
Fonctionnement
Chaque log error ou critical est normalisé (UUIDs, IPs, nombres remplacés) puis hashé. Les occurrences du même hash incrémentent le même groupe.
États d'un groupe
| État | Signification | Action |
|---|---|---|
| Actif | Erreur toujours présente | Résoudre / Ignorer |
| Résolu | Marqué comme corrigé | Rouvre si réapparaît (Régression) |
| Ignoré | Supprimé de la vue active | Rouvre si réapparaît (Régression) |
| Régression 🔴 | Réapparu après résolution/ignoré | Traiter en priorité |
Protection anti-flood
Une même erreur génère au maximum 100 événements facturés par heure. Au-delà, seul le compteur du groupe est mis à jour — l'événement n'est pas stocké dans ClickHouse et n'est pas comptabilisé dans votre quota mensuel.
Accès
Les groupes d'erreurs sont visibles à deux niveaux :
- Serveur → Erreurs — erreurs de ce serveur spécifique
- Projet → Erreurs — toutes les erreurs du compte
Traces distribuées (OTLP)
PulseRadar accepte les spans OpenTelemetry au format OTLP/HTTP JSONet les visualise en waterfall.
Endpoint
POST https://ingest.pulseradar.cloud/v1/traces Authorization: Bearer <API_KEY> X-Server-Id: <SERVER_ID> Content-Type: application/json
Configuration par langage
Variables d'environnement (universel)
export OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.pulseradar.cloud export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <API_KEY>,X-Server-Id=<SERVER_ID>" export OTEL_EXPORTER_OTLP_PROTOCOL=http/json export OTEL_SERVICE_NAME=mon-app
Node.js
npm install @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-http
const { NodeSDK } = require('@opentelemetry/sdk-node')
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http')
new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: 'https://ingest.pulseradar.cloud/v1/traces',
headers: {
'Authorization': 'Bearer <API_KEY>',
'X-Server-Id': '<SERVER_ID>',
},
}),
serviceName: 'mon-app',
}).start()Python
pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(
endpoint="https://ingest.pulseradar.cloud/v1/traces",
headers={"Authorization": "Bearer <API_KEY>", "X-Server-Id": "<SERVER_ID>"}
)))PHP (Laravel)
composer require open-telemetry/sdk open-telemetry/exporter-otlp
# .env OTEL_PHP_AUTOLOAD_ENABLED=true OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.pulseradar.cloud OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <API_KEY>,X-Server-Id=<SERVER_ID>"
Données collectées par span
| Attribut OTLP | Affiché comme |
|---|---|
| service.name | Service |
| span.name / operation | Opération |
| http.method + http.url | Requête HTTP |
| http.status_code | Code HTTP |
| db.system + db.statement | Requête DB |
| duration (start→end) | Durée en ms |
| status.code = 2 | Erreur (rouge) |
Rétention des traces : 7 jours.
Hyperviseurs
PulseRadar collecte les métriques de vos hyperviseurs pour corréler les performances des VMs avec les logs applicatifs.
Proxmox VE
Ajoutez les variables dans /etc/pulseradar/agent.conf :
PROXMOX_HOST=https://pve.example.com:8006 PROXMOX_TOKEN_ID=root@pam!monitoring PROXMOX_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
| Métrique | Description |
|---|---|
| proxmox.node.*.cpu_pct | CPU par node (%) |
| proxmox.node.*.mem_pct | RAM par node (%) |
| proxmox.node.*.disk_pct | Disque par node (%) |
| proxmox.node.*.vms_running | VMs en marche |
| proxmox.vm.*.cpu_pct | CPU par VM (%) |
| proxmox.vm.*.mem_pct | RAM par VM (%) |
VMware vSphere / ESXi
VMWARE_HOST=https://vcenter.example.com VMWARE_USER=monitoring@vsphere.local VMWARE_PASSWORD=your_password
Métriques : hosts connectés, VMs on/off, datastores usage. Requiert vSphere 7+ REST API.
XCP-ng / XenServer
XCPNG_HOST=https://xcp.example.com XCPNG_USER=root XCPNG_PASSWORD=your_password
Nutanix (Prism)
NUTANIX_HOST=https://prism.example.com:9440 NUTANIX_USER=admin NUTANIX_PASSWORD=your_password
Métriques : CPU/RAM/storage cluster, VMs on/off, nombre de nodes.
Alertes
Configurez des règles d'alerte sur vos métriques. Les notifications sont envoyées par email dès qu'un seuil est dépassé, avec cooldown configurable pour éviter le spam.
Types de règles disponibles
| Catégorie | Type | Description |
|---|---|---|
| Logs | level_count | Trop d'erreurs d'un niveau donné |
| Logs | message_contains | Message contient un mot-clé |
| Logs | error_rate | Taux d'erreurs HTTP > seuil |
| Logs | traffic_spike | Pic de trafic anormal |
| APM | apm_p99_latency | Latence P99 > seuil (ms) |
| APM | apm_apdex | Score Apdex (% requêtes rapides) |
| APM | apm_phpfpm_saturation | Saturation PHP-FPM |
| APM | apm_crash_loop | Erreurs 5xx répétées |
| Infra | cpu_high | CPU > seuil (%) |
| Infra | memory_high | RAM > seuil (%) |
| Infra | disk_high | Disque > seuil (%) |
| Infra | server_offline | Serveur hors ligne |
| Cloud | cloud_cpu_high | CPU EC2 > seuil |
| Cloud | cloud_rds_connections | Connexions RDS > seuil |
| Cloud | cloud_alb_error_rate | Erreurs 5xx ALB |
| Cloud | cloud_resource_offline | Ressource cloud offline |
Canaux de notification
Email, Slack, Discord et Webhook. Configurables dans Dashboard → Alertes → Canaux.
Suggestions automatiques
PulseRadar détecte vos services actifs et suggère des règles d'alerte contextuelles dans Dashboard → Alertes → Suggestions. Par exemple : brute force SSH, erreurs PostgreSQL, saturation PHP-FPM, CPU par serveur. Ajoutez-les en un clic.
Cooldown
Le cooldown (défaut : 30 min) empêche le re-déclenchement d'une alerte pendant cette durée après la première notification.
API d'ingestion
Authentification
Authorization: Bearer <API_KEY>
Endpoints d'ingestion
| Méthode | Endpoint | Description |
|---|---|---|
| POST | /v1/logs | Ingestion logs JSON (single ou batch) |
| POST | /v1/logs/fluent-bit | Ingestion format Fluent Bit |
| POST | /v1/logs/cloudflare | Cloudflare Logpush (NDJSON) |
| POST | /v1/logs/drain | Vercel / Netlify log drain |
| POST | /v1/logs/gelf | GELF (Graylog, OVH LDP) |
| POST | /v1/metrics | Métriques serveur (agent) |
| POST | /v1/cloud-metrics | Métriques cloud (AWS EC2/RDS/ALB) |
| POST | /v1/traces | Spans OTLP JSON |
| GET | /health | Statut du service |
Headers optionnels
| Header | Description |
|---|---|
| X-Server-Id | UUID du serveur (pour lier logs/traces/métriques) |
| X-Project-Id | UUID du projet (si multi-projets) |
Limites de débit (rate limiting)
| Plan | Requêtes / minute |
|---|---|
| Free | 60 |
| Starter | 300 |
| Pro | 1 000 |
| Business | 5 000 |
| Scale | 10 000 |
| Enterprise | Illimité |
En cas de dépassement : code HTTP 429 avec header Retry-After: 60.
Lecture des logs (API publique)
GET /v1/logs?project_id=<ID>&level=error&limit=100 Authorization: Bearer <API_KEY>
Clés API
Les clés API sont au niveau du compte (pas du projet). Une seule clé peut ingérer des données pour tous vos projets et serveurs.
Créer une clé
Dashboard → Clés API → Nouvelle clé. Donnez-lui un nom explicite (ex : prod-server-01, laravel-app).
Sécurité
- La clé n'est affichée qu'une seule fois à la création
- Stockée en base sous forme de hash SHA-256
- Révocable instantanément depuis le dashboard
Plans & quotas
Grille tarifaire
| Plan | Events/mois | Rétention logs | Rétention métriques | Prix |
|---|---|---|---|---|
| Free | 200K | 3 jours | 7 jours | 0 €/mois |
| Starter | 2M | 14 jours | 30 jours | 19 €/mois |
| Pro | 10M | 30 jours | 90 jours | 49 €/mois |
| Business | 50M | 90 jours | 180 jours | 99 €/mois |
| Scale | 200M | 180 jours | 1 an | 249 €/mois |
| Enterprise | Illimité | Sur mesure | Sur mesure | Sur devis |
Toutes les fonctionnalités sont incluses dans tous les plans.
Événements facturés vs reçus
Reçus = tous les événements qui arrivent sur l'API d'ingestion.
Facturés = événements écrits dans ClickHouse + forfait métriques.
Forfait métriques
| Ressource | Forfait journalier |
|---|---|
| Serveur actif (agent installé) | 1 000 events/jour |
| Ressource cloud (EC2, RDS, ALB…) | 500 events/jour |
Ce qui n'est jamais facturé
| Source | Raison |
|---|---|
| Métriques serveur (CPU, RAM…) | Couvert par le forfait 1 000/jour |
| Access logs 2xx/3xx | Transformés en métriques agrégées |
| Spans & traces APM | Inclus gratuitement |
| Métriques cloud | Couvert par le forfait 500/jour |
| Logs info/debug (si keep_info=false) | Droppés avant écriture |
| Logs floodés (>100/h identiques) | Flood protection |
Packs supplémentaires
| Pack | Events | Prix |
|---|---|---|
| Pack S | +2M events | 9 € |
| Pack M | +10M events | 19 € |
| Pack L | +50M events | 39 € |
Valables jusqu'à la fin du mois en cours, non reconductibles.
Politique de dépassement
À 80% du quota → alerte email automatique avec estimation du temps restant.
À 100% → l'ingestion continue mais l'accès aux logs est suspendu.
Déblocage immédiat via achat d'un pack ou remise à zéro le 1er du mois.