school
Utilisateur · 12 min

Guide utilisateur LogsCord

Comprendre les colonnes, les types de logs, les expressions et les recherches avancées.

Guide Utilisateur LogsCord

Ce document explique comment lire les logs LogsCord, quelles colonnes existent, quels types de logs sont disponibles et comment écrire des expressions de recherche.

1. Principe

LogsCord est un moteur d'audit pour Discord.

Chaque événement enregistré devient une ligne de log. Une ligne contient :

  • un type (message_delete, member_role_add, voice_join, etc.) ;
  • des identifiants Discord liés à l'action ;
  • une date ;
  • des données détaillées dans extra.

L'utilisateur peut rechercher avec :

  • des filtres simples dans l'interface ;
  • une expression avancée dans le mode Expression.

2. Colonnes Disponibles

ColonneTypeDescriptionExemple
idnombreIdentifiant interne/chronologique du log.1780707318980
typetexteType d'événement Discord."member_role_add"
guildIdtexteID du serveur Discord. Filtré automatiquement par le serveur sélectionné."758391511338844221"
executortexte/nullID de l'utilisateur qui a effectué l'action, quand connu."1341946276601663511"
targettexte/nullID de l'utilisateur, rôle ou objet ciblé, quand connu."1280262760797704245"
channeltexte/nullID du salon principal lié au log."112233445566778899"
fromtexte/nullAncienne valeur, souvent ancien salon vocal ou ancienne cible."111111111111111111"
totexte/nullNouvelle valeur, souvent nouveau salon vocal ou nouvelle cible."222222222222222222"
roletexte/nullID de rôle quand le log concerne un rôle unique."333333333333333333"
createdAtnombreDate du log en timestamp millisecondes.1780707318980
extraJSONDétails variables selon le type de log.{ "content": "hello" }

À Retenir

CasChamp utile
Chercher un type d'événementtype
Chercher ce qu'un modérateur a faitexecutor
Chercher ce qui est arrivé à un membretarget ou executor selon le type
Chercher dans un salonchannel, from, to
Chercher par périodesélecteur de période ou createdAt
Chercher dans le contenu d'un messageextra.content
Chercher par ID de messageextra.messageId
Chercher dans un tableau JSONextra.roles[*].id, extra.attachments[*].url, etc.

3. Types De Logs

La liste ci-dessous correspond aux types affichables/recherchables par LogsCord côté client. Certains types peuvent dépendre des événements réellement collectés par le bot, de ses permissions Discord et des modules activés.

Modération Automatique

TypeNom affichéDescription
auto_moderation_rule_createCréation de règle de modération automatiqueUne règle AutoMod Discord a été créée.
auto_moderation_rule_updateMise à jour de règle de modération automatiqueUne règle AutoMod Discord a été modifiée.
auto_moderation_rule_deleteSuppression de règle de modération automatiqueUne règle AutoMod Discord a été supprimée.
auto_moderation_flag_to_channelSignalement en salonAutoMod a signalé un message dans un salon.
auto_moderation_block_messageMessage bloqué par modération automatiqueAutoMod a bloqué un message.
automod_action_executionAction effectuée par la modération automatiqueAutoMod a exécuté une action.

Messages

TypeNom affichéDescription
message_createMessage envoyéUn message a été envoyé.
message_editMessage modifiéUn message a été modifié.
message_deleteMessage suppriméUn message a été supprimé.
message_bulk_deleteSuppression massive de messagesPlusieurs messages ont été supprimés en masse.
message_reaction_addAjout de réactionUne réaction a été ajoutée à un message.
message_reaction_removeRetrait de réactionUne réaction a été retirée d'un message.

Vocal

TypeNom affichéDescription
voice_joinConnexion vocaleUn membre a rejoint un salon vocal.
voice_moveDéplacement vocalUn membre a changé de salon vocal.
voice_leaveDéconnexion vocaleUn membre a quitté un salon vocal.
voice_state_updateMise à jour de l'état vocalL'état vocal d'un membre a changé.
voice_state_videoÉtat vidéo activé/désactivéLa caméra d'un membre a été activée ou désactivée.
voice_state_streamÉtat streaming activé/désactivéLe streaming d'un membre a été activé ou désactivé.
member_moveDéplacement de membreUn membre a été déplacé.
member_disconnectDéconnexion de membreUn membre a été déconnecté d'un salon vocal.

Membres

TypeNom affichéDescription
member_joinArrivée d'un membreUn membre a rejoint le serveur.
member_leaveDépart d'un membreUn membre a quitté le serveur.
member_timeout_createTimeout crééUn timeout a été appliqué.
member_timeout_cancelTimeout annuléUn timeout a été annulé.
member_timeout_updateTimeout mis à jourUn timeout a été modifié.
member_ban_addBannissementUn membre a été banni.
member_ban_removeDébannissementUn membre a été débanni.
member_kickExpulsion de membreUn membre a été expulsé.
member_update_guild_avatarChangement d'avatar de guildeL'avatar serveur d'un membre a changé.
member_update_guild_bannerChangement de bannière de guildeLa bannière serveur d'un membre a changé.
member_update_nicknameChangement de surnomLe surnom serveur d'un membre a changé.
member_role_addAjout de rôleUn ou plusieurs rôles ont été ajoutés à un membre.
member_role_removeSuppression de rôleUn ou plusieurs rôles ont été retirés d'un membre.
member_mute_activatedActivation du muteLe mute vocal serveur a été activé.
member_mute_deactivatedDésactivation du muteLe mute vocal serveur a été désactivé.
member_deaf_activatedActivation du deafLe deaf vocal serveur a été activé.
member_deaf_deactivatedDésactivation du deafLe deaf vocal serveur a été désactivé.

Utilisateurs

TypeNom affichéDescription
user_update_usernameChangement de nom d'utilisateurLe username Discord d'un utilisateur a changé.
user_update_globalnameChangement de nom globalLe nom global Discord a changé.
user_update_avatarChangement d'avatarL'avatar Discord a changé.
user_update_bannerChangement de bannièreLa bannière Discord a changé.
presence_updateMise à jour de la présenceLe statut ou les activités d'un membre ont changé.

Salons Et Permissions

TypeNom affichéDescription
channel_createCréation de salonUn salon a été créé.
channel_updateMise à jour de salonUn salon a été modifié.
channel_deleteSuppression de salonUn salon a été supprimé.
channel_position_updateMise à jour de la position d'un salonL'ordre des salons a changé.
channel_overwrite_createCréation d'une autorisation de salonUne permission spécifique de salon a été créée.
channel_overwrite_updateMise à jour d'une autorisation de salonUne permission spécifique de salon a été modifiée.
channel_overwrite_deleteSuppression d'une autorisation de salonUne permission spécifique de salon a été supprimée.

Rôles

TypeNom affichéDescription
role_createCréation de rôleUn rôle a été créé.
role_updateMise à jour de rôleUn rôle a été modifié.
role_deleteSuppression de rôleUn rôle a été supprimé.
role_position_updateMise à jour de la position d'un rôleL'ordre des rôles a changé.

Serveur

TypeNom affichéDescription
guild_availableServeur disponibleLe bot a vu le serveur comme disponible.
bot_addAjout de botUn bot a été ajouté au serveur.

Émojis Et Invitations

TypeNom affichéDescription
emoji_createCréation d'émojiUn émoji a été créé.
emoji_updateMise à jour d'émojiUn émoji a été modifié.
emoji_deleteSuppression d'émojiUn émoji a été supprimé.
invite_createCréation d'une invitationUne invitation Discord a été créée.
invite_updateMise à jour d'une invitationUne invitation Discord a été modifiée.
invite_deleteSuppression d'une invitationUne invitation Discord a été supprimée.

Logs Historiques Ou Personnalisés

Ces types existent dans le rendu client, mais peuvent provenir d'anciens imports, d'intégrations ou de données historiques.

TypeNom affichéDescription
sanction_blacklistBlacklistBlacklist custom historique.
sanction_unblacklistUnblacklistRetrait de blacklist custom historique.
sanction_muteSanction: MuteMute custom historique.
sanction_unmuteSanction: UnmuteRetrait de mute custom historique.
sanction_warnSanction: AvertissementAvertissement custom historique.
utils_voice_find=find (Crowbot)Log vocal utilitaire historique.
utils_voice_join=join (Crowbot)Log vocal utilitaire historique.
utils_voice_move=mv (Crowbot)Log vocal utilitaire historique.

4. Données extra Fréquentes

extra contient les détails qui changent selon le type de log.

CheminTypes fréquentsDescription
extra.contentmessage_create, message_edit, message_deleteContenu textuel du message.
extra.messageIdlogs messagesID Discord du message.
extra.attachmentslogs messagesListe des pièces jointes.
extra.attachments[*].urllogs messagesURL d'une pièce jointe.
extra.embedslogs messagesEmbeds du message.
extra.mentions.userslogs messagesIDs des utilisateurs mentionnés.
extra.mentions.roleslogs messagesIDs des rôles mentionnés.
extra.rolesmember_role_add, member_role_removeListe des rôles ajoutés/retirés.
extra.roles[*].idrôles membreID d'un rôle dans la liste.
extra.roles[*].namerôles membreNom d'un rôle dans la liste.
extra.reasonmodérationRaison fournie par Discord/audit log.
extra.durationtimeoutDurée d'un timeout.
extra.oldPresencepresence_updateAncienne présence.
extra.newPresencepresence_updateNouvelle présence.

5. Expressions De Recherche

Dans l'onglet Filtrer les logs, le mode Expression permet d'écrire une requête avancée.

Syntaxe Générale

txtchamp opérateur valeur

Exemples :

txttype == "message_delete"
txtexecutor == "123456789012345678"
txttype == "member_role_add" and target == "123456789012345678"

Valeurs

ValeurExempleNotes
Texte"message_delete"Toujours entre guillemets doubles.
Nombre1780707318980Utile pour id ou createdAt.
Ensemble{ "a", "b", "c" }Utilisé avec in ou not in.

Les ensembles acceptent actuellement des chaînes.

6. Champs Utilisables Dans Les Expressions

ChampTypeOptimisé ClickHouseDescription
idnombreouiIdentifiant du log.
typetexteouiType du log.
guildIdtexteouiServeur. Normalement géré par LogsCord.
executortexteouiAuteur de l'action.
targettexteouiCible de l'action.
channeltexteouiSalon principal.
fromtexteouiAncienne valeur/salon.
totexteouiNouvelle valeur/salon.
roletexteouiRôle principal.
createdAtnombreouiTimestamp du log.
extra.contenttexteouiContenu de message.
extra.messageIdtexteouiID du message.
extra.<array>[*]texteoui si comparaison simpleProjection dans un tableau JSON scalaire de extra.
extra.<array>[*].<field>texteoui si comparaison simpleProjection d'un champ dans un tableau d'objets JSON de extra.

7. Opérateurs

OpérateurDescriptionExemple
andLes deux conditions doivent être vraies.type == "message_delete" and executor == "123"
orAu moins une condition doit être vraie.type == "message_delete" or type == "message_edit"
notInverse une condition.not is_bot(executor)
==Égal à.type == "member_join"
!=Différent de.type != "presence_update"
>Supérieur à.createdAt > 1780000000000
>=Supérieur ou égal à.createdAt >= 1780000000000
<Inférieur à.createdAt < 1781000000000
<=Inférieur ou égal à.createdAt <= 1781000000000
inLa valeur est dans un ensemble.type in { "message_delete", "message_edit" }
not inLa valeur n'est pas dans un ensemble.type not in { "presence_update" }

Aliases acceptés :

AliasÉquivalent
eq==
ne!=
gt>
ge>=
lt<
le<=

8. Fonctions Appelables

FonctionArgumentsOptimisée ClickHouseDescriptionExemple
lower(value)1ouiConvertit une valeur texte en minuscules.lower(extra.content) == "hello"
contains(value, needle)2ouiVérifie qu'un texte contient une sous-chaîne.contains(extra.content, "discord.gg")
match(value, regex)2ouiVérifie une expression régulière.match(extra.content, "discord\\\\.gg")
exists(value)1ouiVérifie qu'une valeur existe/n'est pas vide.exists(extra.messageId)
length(value)1ouiRetourne la taille d'une chaîne ou d'un tableau.length(extra.embeds) > 0
is_bot(userId)1nonVérifie si l'ID correspond à un bot du serveur.not is_bot(executor)
roles(userId)1nonRetourne les rôles actuels du membre sous forme { id, name }[].roles(executor)[*].id in { "ROLE_ID" }

Important : is_bot() demande une vérification runtime côté serveur. Une expression qui utilise is_bot() peut être moins optimisable qu'une expression purement SQL.

roles() utilise les rôles actuels du membre sur le serveur, pas forcément les rôles historiques au moment exact du log. Pour les logs member_role_add et member_role_remove, préférer extra.roles[*].id si l'objectif est de filtrer les rôles concernés par l'action.

9. Projections Dans extra

Les projections permettent de chercher dans un tableau JSON stocké dans extra.

Syntaxe :

txtextra.<cheminDuTableau>[*]
extra.<cheminDuTableau>[*].<champ>

Exemples :

txtextra.roles[*].id in { "1483959882142060624" }
txtextra.mentions.users[*] in { "1464758198291529953" }
txtextra.roles[*].name == "Majeur"
txtextra.attachments[*].url == "https://example.com/image.png"
txtextra.audit.roles[*].meta.id in { "42" }

Règles :

RègleDétail
Racine obligatoireLa projection doit commencer par extra.
Une projection maximumUne seule partie [*] dans le chemin.
Champ final optionnelUtiliser extra.roles[*].id pour un tableau d'objets et extra.mentions.users[*] pour un tableau de valeurs scalaires.
Comparaison supportée==, !=, in, not in.

Index [i]

Il est aussi possible de récupérer un élément précis avec un index numérique.

Les index commencent à 0.

txtextra.embeds[0].description == "raid"
contains(extra.embeds[0].description, "raid")
extra.content[0] == "!"

Si la valeur est un tableau, [i] récupère l'élément à l'index demandé. Si la valeur est une chaîne, [i] récupère le caractère correspondant.

10. Exemples Utiles

Messages

ObjectifExpression
Messages suppriméstype == "message_delete"
Messages modifiés ou suppriméstype in { "message_delete", "message_edit" }
Messages contenant une invitation Discordcontains(extra.content, "discord.gg")
Messages avec au moins un embedlength(extra.embeds) > 0
Premier embed contenant un textecontains(extra.embeds[0].description, "raid")
Message précis par IDextra.messageId == "123456789012345678"
Message supprimé par un utilisateur précistype == "message_delete" and executor == "123456789012345678"

Rôles

ObjectifExpression
Tous les ajouts de rôlestype == "member_role_add"
Tous les retraits de rôlestype == "member_role_remove"
Ajout d'un rôle précistype == "member_role_add" and extra.roles[*].id in { "1483959882142060624" }
Retrait d'un rôle précistype == "member_role_remove" and extra.roles[*].id in { "1483959882142060624" }
Rôle par nomextra.roles[*].name == "Majeur"

Modération

ObjectifExpression
Banstype == "member_ban_add"
Débanstype == "member_ban_remove"
Kickstype == "member_kick"
Timeouts crééstype == "member_timeout_create"
Sanctions d'un modérateurtype in { "member_ban_add", "member_kick", "member_timeout_create" } and executor == "123456789012345678"

Vocal

ObjectifExpression
Connexions vocalestype == "voice_join"
Déconnexions vocalestype == "voice_leave"
Déplacements vocauxtype == "voice_move"
Activité vocale d'un membretype in { "voice_join", "voice_leave", "voice_move" } and target == "123456789012345678"
Mouvements vers un salon précistype == "voice_move" and to == "123456789012345678"

Dashboards Personnalisés

ObjectifExpression dataset
Membres arrivéstype == "member_join"
Membres partistype == "member_leave"
Messages envoyéstype == "message_create"
Rôle spécifique ajoutétype == "member_role_add" and extra.roles[*].id in { "1483959882142060624" }
Modération hors botstype in { "member_ban_add", "member_kick", "member_timeout_create" } and not is_bot(executor)
Actions faites par quelqu'un qui a actuellement un rôleroles(executor)[*].id in { "1483959882142060624" }
Actions visant quelqu'un qui a actuellement un rôleroles(target)[*].id in { "1483959882142060624" }

11. Priorités Et Parenthèses

L'ordre logique est :

1. parenthèses ; 2. not ; 3. comparaisons ; 4. and ; 5. or.

Utiliser des parenthèses dès qu'il y a un doute :

txt(type == "message_delete" or type == "message_edit") and executor == "123"

Sans parenthèses, une expression complexe peut être correcte techniquement mais ambiguë pour un humain.

12. Expressions Sans Filtre

Certaines expressions sont valides mais ne filtrent rien. LogsCord les nettoie avant de générer la requête SQL.

ExpressionComportement
champ videRecherche normale sans filtre expression.
""Recherche normale sans filtre expression.
"texte"Recherche normale sans filtre expression.
123Recherche normale sans filtre expression.
type == "message_create" and ""Garde seulement type == "message_create".
type == "message_create" or ""Devient une recherche normale sans filtre expression.

Un champ nu est converti en test d'existence :

txtextra.content

équivaut à :

txtexists(extra.content)

13. Limites Et Bonnes Pratiques

SujetRecommandation
PerformanceToujours commencer par type == ... ou type in { ... } quand possible.
PériodeUtiliser le sélecteur de période de l'interface pour réduire le volume.
RegexGarder les regex simples.
is_bot()À utiliser si nécessaire, mais moins optimisable.
extraPréférer les chemins connus comme extra.content, extra.messageId, extra.roles[*].id.
DashboardsÉviter les expressions runtime non optimisables pour les grands volumes.

Limites techniques actuelles :

  • profondeur d'expression limitée ;
  • nombre de noeuds limité ;
  • nombre de valeurs dans un ensemble limité ;
  • longueur des regex limitée ;
  • projection JSON autorisée uniquement sous extra ;
  • les dashboards agrégés sont plus performants quand toute l'expression est poussée dans ClickHouse.

14. Lire Une Réponse De Recherche

Une réponse de recherche contient généralement :

ChampDescription
resultListe des logs trouvés.
membersMembres résolus pour affichage.
channelsSalons résolus pour affichage.
explanationDétails techniques de la recherche.
explanation.expression.astArbre de l'expression. Utile pour debug.
explanation.expression.plan.prewherePartie optimisée en PREWHERE.
explanation.expression.plan.wherePartie optimisée en WHERE.
explanation.expression.plan.residualPartie évaluée côté Node après ClickHouse.
explanation.expression.sqlRequête SQL générée avec noms de paramètres.

Pour un utilisateur final, le plus important est result. Pour diagnostiquer une recherche lente ou incorrecte, regarder plan.residual.

15. Résumé Rapide

Expressions les plus utiles :

txttype == "message_delete"
txttype in { "message_delete", "message_edit" } and executor == "USER_ID"
txtcontains(extra.content, "discord.gg")
txttype == "member_role_add" and extra.roles[*].id in { "ROLE_ID" }
txttype in { "member_ban_add", "member_kick", "member_timeout_create" } and not is_bot(executor)