Autres jeux (API REST)
L'intégration API est réservée au propriétaire du serveur de jeux.
Si votre jeu n'a pas de plugin dédié, vous pouvez intégrer QuantumLogs via l'API REST directement. Cette méthode fonctionne avec n'importe quel langage de programmation.
Endpoint
POST /logs
Authentification
Envoyez votre clé API dans le header Authorization :
Authorization: votre-cle-api-ici
La clé est envoyée directement dans le header, sans préfixe Bearer. C'est le format attendu par QuantumLogs.
Format de la requête
Le body est un tableau JSON de logs. Chaque élément du tableau est un objet log :
[
{
"measurement": "player_kill",
"timestamp": "2025-01-15T14:30:45.123Z",
"tags": {
"player_name": "John",
"player_id": "12345",
"player_global_id": "76561198000000000",
"target_name": "Jane",
"target_id": "67890",
"target_global_id": "76561198000000001",
"server": "serveur-1"
},
"fields": {
"value": "John a tué Jane avec AK-47 à 50m (headshot)"
},
"metadata": {
"weapon": "AK-47",
"distance": 50,
"bodypart": "head"
}
}
]
Champs détaillés
Champs obligatoires
| Champ | Type | Description |
|---|---|---|
measurement | string | Type/catégorie du log (ex: kill, chat, connect) |
timestamp | string (ISO 8601) | Horodatage du log (ex: 2025-01-15T14:30:45.123Z) |
fields | object | Objet contenant le champ value |
fields.value | string | Contenu textuel du log (c'est ce qui s'affiche dans la colonne "Valeur") |
tags | object | Objet contenant les tags d'indexation (peut être vide {}) |
Tous ces champs sont obligatoires. L'objet tags doit être présent même s'il est vide ({}). Le timestamp doit être au format ISO 8601 — il n'y a pas de valeur par défaut côté serveur.
Tags reconnus par le backend
Seuls les noms de tags listés ci-dessous sont reconnus. Tout tag avec un nom différent sera silencieusement ignoré et n'apparaîtra pas dans vos logs. C'est la cause la plus fréquente de "logs qui ne fonctionnent pas".
| Tag | Type | Description |
|---|---|---|
player_name | string | Nom du joueur |
player_id | string | ID du joueur (spécifique au serveur, ex: ID de personnage) |
player_global_id | string | Identifiant unique global du joueur (Steam ID 64, UUID, etc.) |
player_steamid | string | Steam ID (déprécié, utilisez player_global_id) |
target_name | string | Nom de la cible |
target_id | string | ID de la cible |
target_global_id | string | Identifiant unique global de la cible |
target_steamid | string | Steam ID de la cible (déprécié) |
server | string | Identifiant du serveur source |
Tous les tags sont optionnels, mais server est fortement recommandé — il est utilisé pour le comptage de serveurs actifs et le contrôle des limites de votre plan.
Exemples de tags invalides (seront ignorés) :
weapon,distance,map→ Mettez ces infos dansfields.valueou dansmetadataattacker_name,victim_name→ Utilisezplayer_nameettarget_nameadmin_name→ Utilisezplayer_name
Champs optionnels
| Champ | Type | Description |
|---|---|---|
metadata | object | Données JSON supplémentaires libres (visible dans le détail du log, non filtrable) |
Codes de réponse
Succès
| Code | Body | Description |
|---|---|---|
| 201 | OK | Logs reçus et insérés avec succès |
Erreurs
| Code | Description | Détail |
|---|---|---|
| 401 | Clé API invalide ou manquante | { "statusCode": 401, "message": "Missing authorization header" } ou { "statusCode": 401, "message": "Invalid API key" } |
| 413 | Body trop volumineux | La taille maximale du body est de 50 Mo |
| 429 | Limite de serveurs dépassée | Voir détail ci-dessous |
| 500 | Erreur serveur | Injection bloquée (plan expiré/suspendu) ou erreur de base de données |
Détail de la réponse 429
Si vous dépassez le nombre de serveurs autorisés par votre plan, la réponse contient des informations utiles :
{
"statusCode": 429,
"error": "Server Limit Exceeded",
"message": "You have reached your server limit (5). Upgrade your plan to add more servers.",
"upgradeUrl": "https://quantumlogs.com/pricing",
"activeServers": ["rp-1", "rp-2", "pvp-1", "event-1", "test"],
"maxServers": 5
}
Les serveurs actifs sont suivis pendant 24 heures. Un serveur qui n'envoie plus de logs pendant 24h libère automatiquement une place.
Bonnes pratiques
Envoi par lots
Envoyez vos logs par lots plutôt qu'un par un. Un intervalle de 10 secondes est recommandé :
- Accumulez les logs dans une file d'attente en mémoire
- Toutes les 10 secondes, envoyez le lot complet en une seule requête
- Videz la file après un envoi réussi
Tout dans fields.value
Le champ value est le contenu principal de votre log. Mettez-y toutes les informations lisibles. Les tags ne servent qu'à l'indexation (recherche par joueur, serveur, etc.).
// CORRECT - toutes les infos dans value
{
"measurement": "player_kill",
"timestamp": "2025-01-15T14:30:45.123Z",
"fields": { "value": "John a tué Jane avec AK-47 à 50m (headshot)" },
"tags": { "player_name": "John", "target_name": "Jane", "server": "rp-1" }
}
// INCORRECT - les données custom dans les tags sont ignorées
{
"measurement": "player_kill",
"timestamp": "2025-01-15T14:30:45.123Z",
"tags": { "weapon": "AK-47", "distance": "50", "bodypart": "head" },
"fields": { "value": "" }
}
Metadata pour les données structurées
Si vous avez besoin de stocker des données structurées en plus du texte, utilisez metadata :
{
"measurement": "player_kill",
"timestamp": "2025-01-15T14:30:45.123Z",
"fields": { "value": "John a tué Jane avec AK-47 à 50m (headshot)" },
"tags": { "player_name": "John", "target_name": "Jane", "server": "rp-1" },
"metadata": {
"weapon": "AK-47",
"distance": 50,
"bodypart": "head",
"position": { "x": 1234.5, "y": -567.89, "z": 100.23 }
}
}
Les métadonnées sont stockées en JSON et visibles dans le détail du log, mais ne sont pas filtrables via les filtres classiques.
Gestion des erreurs
- En cas d'erreur réseau, conservez les logs en mémoire et réessayez
- Implémentez un retry avec backoff exponentiel
- Envoyez les logs restants à l'arrêt du serveur (flush)
Exemples
cURL
curl -X POST https://votre-instance.quantumlogs.cloud/logs \
-H "Content-Type: application/json" \
-H "Authorization: votre-cle-api" \
-d '[{
"measurement": "test",
"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%S.000Z)'",
"fields": { "value": "Log de test depuis cURL" },
"tags": { "server": "test-server" }
}]'
Python
import requests
import json
from datetime import datetime, timezone
API_URL = "https://votre-instance.quantumlogs.cloud/logs"
API_KEY = "votre-cle-api"
logs = [{
"measurement": "player_connection",
"timestamp": datetime.now(timezone.utc).isoformat(),
"tags": {
"player_name": "John",
"player_global_id": "76561198000000000",
"server": "serveur-1"
},
"fields": {
"value": "John s'est connecté au serveur"
}
}]
response = requests.post(
API_URL,
headers={
"Content-Type": "application/json",
"Authorization": API_KEY
},
json=logs
)
print(f"Status: {response.status_code}") # 201 = succès
print(f"Body: {response.text}") # "OK"
JavaScript (Node.js)
const API_URL = "https://votre-instance.quantumlogs.cloud/logs";
const API_KEY = "votre-cle-api";
const logs = [{
measurement: "player_connection",
timestamp: new Date().toISOString(),
tags: {
player_name: "John",
player_global_id: "76561198000000000",
server: "serveur-1"
},
fields: {
value: "John s'est connecté au serveur"
}
}];
const response = await fetch(API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": API_KEY
},
body: JSON.stringify(logs)
});
console.log(`Status: ${response.status}`); // 201 = succès
console.log(`Body: ${await response.text()}`); // "OK"
C# (Unity / .NET)
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "votre-cle-api");
var logs = new[] {
new {
measurement = "player_connection",
timestamp = DateTime.UtcNow.ToString("o"),
tags = new { player_name = "John", server = "serveur-1" },
fields = new { value = "John s'est connecté" }
}
};
var content = new StringContent(
JsonSerializer.Serialize(logs),
Encoding.UTF8,
"application/json"
);
var response = await client.PostAsync(
"https://votre-instance.quantumlogs.cloud/logs",
content
);
Console.WriteLine($"Status: {(int)response.StatusCode}"); // 201 = succès
Lua (Garry's Mod - exemple custom)
local API_URL = "https://votre-instance.quantumlogs.cloud/logs"
local API_KEY = "votre-cle-api"
local logs = {
{
measurement = "player_chat",
timestamp = os.date("!%Y-%m-%dT%H:%M:%S.000Z"),
tags = {
player_name = "John",
player_global_id = "76561198000000000",
server = "darkrp-1"
},
fields = {
value = "John: Bonjour tout le monde !"
}
}
}
HTTP({
url = API_URL,
method = "POST",
headers = {
["Content-Type"] = "application/json",
["Authorization"] = API_KEY
},
body = util.TableToJSON(logs),
success = function(code, body)
print("QuantumLogs: " .. code) -- 201 = succès
end,
failed = function(reason)
print("QuantumLogs Error: " .. reason)
end
})