Logging structuré (JSON Lines)
gAgent dispose de deux systèmes de logs indépendants et complémentaires :
Le mode JSON Lines est conçu pour l’ingestion dans des outils comme ELK (Elasticsearch/Kibana) ou Grafana/Loki.
Activation
Définir la variable d’environnement GAGENT_LOG avec le chemin du fichier
de sortie avant de lancer l’application :
GAGENT_LOG=gagent.jsonl ./build/tests/test_subscribe_notify
# ou pour une démo
GAGENT_LOG=/var/log/gagent/events.jsonl ./build/examples/demo_visualization
Si GAGENT_LOG n’est pas défini, les appels logJson() sont des no-ops
(aucun overhead en production).
Format d’une ligne
Chaque ligne est un objet JSON autonome (JSON Lines / NDJSON) :
{"ts":"2026-03-24T10:00:00.123Z","event":"acl_send","from":"alice","to":"bob","perf":"request","conv":"cnp-alice-75727","content":"compute-plan"}
Les champs communs à toutes les lignes :
Champ |
Description |
|---|---|
|
Horodatage UTC ISO 8601 avec milliseconde ( |
|
Type d’événement (voir ci-dessous) |
Événements émis
agent_start
Émis dans Agent::_init() après l’enregistrement AMS, une fois par agent
au démarrage de son processus child.
{"ts":"...","event":"agent_start","agent":"alice","pid":"12345"}
Champ |
Description |
|---|---|
|
Nom de l’agent ( |
|
PID du processus child |
agent_stop
Émis dans Agent::doDelete() avant le désenregistrement AMS/DF.
{"ts":"...","event":"agent_stop","agent":"alice","pid":"12345"}
agent_lifecycle
Émis à chaque transition d’état dans control_Thread().
{"ts":"...","event":"agent_lifecycle","agent":"alice","state":"suspended"}
États possibles : active, suspended, waiting, waking,
transit.
acl_send
Émis dans AclMQ::acl_send() après chaque envoi réussi.
{"ts":"...","event":"acl_send","from":"monitor","to":"sensor","perf":"subscribe","conv":"snp-monitor-75727","content":"temperature"}
Champ |
Description |
|---|---|
|
Expéditeur (champ |
|
Destinataire (nom de la queue cible) |
|
Performative FIPA ( |
|
Identifiant de conversation ( |
|
Contenu du message, tronqué à 120 caractères |
acl_recv
Émis dans AclMQ::acl_receive() après chaque réception réussie.
{"ts":"...","event":"acl_recv","to":"sensor","from":"monitor","perf":"subscribe","conv":"snp-monitor-75727","content":"temperature"}
Champs identiques à acl_send (rôles from/to inversés).
Utilisation depuis le code C++
La macro LOG_JSON est disponible en incluant Logger.hpp :
#include <gagent/utils/Logger.hpp>
// Dans un Behaviour ou un Agent
LOG_JSON("mon_event", {
{"agent", "alice"},
{"detail", some_string},
{"count", std::to_string(n)},
});
Toutes les valeurs sont des chaînes. Pour émettre des champs numériques,
utiliser std::to_string().
Appel direct sur le singleton :
gagent::Logger::getInstance().logJson("mon_event", {
{"key", "value"},
});
Exploitation avec jq
# Suivre les messages en temps réel
tail -f gagent.jsonl | jq .
# Filtrer les envois d'une conversation
jq 'select(.event=="acl_send" and .conv=="cnp-alice-75727")' gagent.jsonl
# Compter les messages par performative
jq -r '.perf' gagent.jsonl | sort | uniq -c | sort -rn
# Chronologie d'un agent
jq 'select(.agent=="alice")' gagent.jsonl
Intégration ELK / Grafana Loki
Le format JSON Lines est nativement reconnu par Filebeat :
# filebeat.yml (extrait)
filebeat.inputs:
- type: log
paths: ["/var/log/gagent/*.jsonl"]
json.keys_under_root: true
json.add_error_key: true
output.elasticsearch:
hosts: ["localhost:9200"]
Pour Grafana Loki avec Promtail :
# promtail-config.yml (extrait)
scrape_configs:
- job_name: gagent
static_configs:
- targets: [localhost]
labels:
job: gagent
__path__: /var/log/gagent/*.jsonl
pipeline_stages:
- json:
expressions:
event: event
agent: agent
perf: perf