J’utilise MongoDB de manière un peu forcée, car j’utilise une application qui en a besoin (RocketChat)
Et franchement ce n’est pas évident de s’y retrouver, même pour certaines choses basiques, par exemple la liste des requêtes en cours d’exécution
Peut être car je n’ai pas l’habitude, que je ne suis pas assez formé ou même borné … mais en tout cas j’ai trouvé la solution et je vous la partage aujourd’hui

Comment afficher la liste des requêtes en cours sur MongoDB?
MongoDB est assez particulier dans son fonctionnement, et la seule possibilité de voir cela par défaut est d’utiliser la commande db.currentOp()
Celle-ci vous affichera la liste des opérations en cours, au format JSON, donc pas très facile à lire

Heureusement je vous ai trouvé un script python qui va améliorer cela, et je vous le présente dans cet article
Je reviens d’abord très rapidement sur la structure d’une base MongoDB, et le currentOp()

Principe de MongoDB

Base de données

Une base de donnée MongoDB est composée d’un ensemble de collections (l’équivalent d’une table en MySQL)
Chaque collection est semblable à un gros fichier JSON, ou chaque enregistrement est un ensemble de données au format JSON, par exemple:

{
    prenom: "John",
    nom: "Smith",
    age: "30"
}

Requètes

Au niveau des requêtes, il s’agit d’instructions, très proches de ce qu’on pourrait trouver dans du jQuery par exemple

Voici quelques exemples pour vous donner une idée:

db.inventory.find( { statut: "1" } )
db.products.insertOne( { item: "card", qty: 15 } );

Si l’instruction est simple à deviner si l’on comprend un minimum l’anglais, vous imaginez bien que dès que vous insérez plusieurs enregistrements dans la meme requête et que chaque enregistrement à une quinzaine de valeurs, l’état des requêtes en cours devient illisible

C’est pourquoi j’ai cherché une autre manière d’afficher les résultats, nous verrons cela par la suite

Le processlist facon MongoDB

L’instruction db.currentOp()

MongoDB propose bien une solution avec db.currentOp()

Cette instruction tapée dans le shell Mongo renvoie un document contenant des informations sur les opérations en cours pour l’instance de base de données
Cela semble exactement ce que l’on souhaite non ?

Eh bien en théorie oui, mais l’affichage n’est vraiment pas utilisable lorsque vous avez 200 requêtes en meme temps

L’affichage du résultat

Pour afficher le currentOp() sur votre serveur Mongo, suivez les étapes suivantes:

  • Connectez vous au shell Mongo
    mongo

    Par défaut c’est suffisant, si vous avez changé des choses à votre serveur, pensez à ajouter le port, l’utilisateur et le mot de passe par exemple

  • Tapez l’instruction suivante
    db.currentOp()
  • Voici le résultat que j’obtiens sur ma machine de test:
    > db.currentOp()
    {
    	"inprog" : [
    		{
    			"host" : "PingusPC:27017",
    			"desc" : "conn",
    			"threadId" : "140625830995712",
    			"connectionId" : 1,
    			"client" : "127.0.0.1:37558",
    			"appName" : "MongoDB Shell",
    			"clientMetadata" : {
    				"application" : {
    					"name" : "MongoDB Shell"
    				},
    				"driver" : {
    					"name" : "MongoDB Internal Client",
    					"version" : "3.6.3"
    				},
    				"os" : {
    					"type" : "Linux",
    					"name" : "Ubuntu",
    					"architecture" : "x86_64",
    					"version" : "18.04"
    				}
    			},
    			"active" : true,
    			"currentOpTime" : "2018-12-08T09:11:03.391+0100",
    			"opid" : 610,
    			"secs_running" : NumberLong(0),
    			"microsecs_running" : NumberLong(138),
    			"op" : "command",
    			"ns" : "admin.$cmd.aggregate",
    			"command" : {
    				"currentOp" : 1,
    				"$db" : "admin"
    			},
    			"numYields" : 0,
    			"locks" : {
    				
    			},
    			"waitingForLock" : false,
    			"lockStats" : {
    				
    			}
    		}
    	],
    	"ok" : 1
    }
    

    Tout ca pour dire qu’il n’y a aucune requête en cours 🙂

Si vous avez des requêtes en cours, elle s’ajoute à la fin, au même format JSON, avec une ligne par champ recherché ou modifié

Cela me pose deux problèmes:

  • Si vous avez 30 requêtes en cours, l’affichage est illisible, il est très compliqué de savoir ce qui tourne, depuis combien de temps et si c’est normal que ce soit en cours
  • L’affichage n’est pas rafraîchi en temps réel. Il est possible d’avoir 30 requêtes en simultané et rien 1s plus tard. Il sera très difficile de debugger un problème si vous devez lancer la commande à la main à chaque fois

Encore une fois je ne suis pas un expert en MongoDB, peut être qu’il y a une astuce pour faire cela, mais je ne l’ai pas trouvé
Pas contre j’ai trouvé un script qui est exactement ce que je cherchais
Et la simple existence de ce script me laisse penser qu’il n’y a pas d’astuce dans Mongo directement 🙂

Le processlist façon MySQL

Code du script Python

Après de rapides recherches d’une solution plus proche de MySQL, je suis donc tombé assez rapidement sur ce script sur Github: mongodb_process_checker.py

Il s’agit d’un script en python, il vous faudra donc installer python ainsi que quelques modules
Sur Ubuntu vous pouvez utiliser la ligne de commande suivante:

sudo apt-get install python python-pymongo python-argparse python-prettytable

Ensuite télécharger le fichier et placez le dans le dossier de votre choix
Vous pouvez aussi simplement copier/coller le code bruit dans votre éditeur préféré, et enregistrer le script avec l’extension .py

Utilisation

L’utilisation est très simple, pour une installation par défaut il suffit de lancer le script sans paramètre:

python mongodb_process_checker.py

Par contre si vous avez sécurisé votre installation ou changez le port, vous devrez spécifier des paramètres supplémentaires, par exemple:

python mongodb_process_checker.py  -P 27017 -u utilisateur -p motdepasse -a base

-P: port d’écoute de mongodb
-u: nom d’utilisateur
-p: mot de passe de l’utilisateur
-a: base de donnée à utiliser pour l’authentification

Affichage

Une fois le script lancé, vous aurez un affichage de cette forme:

Timestamp : 2018-12-08 09:22:08                    [Refresh Int : 4 Sec]

Connected To : localhost:27017/admin               [StandAlone]

+-------+-----------+----------------------+---------+----------+-------+
| Op-ID | Host      | Collection           | Op      | Duration | Query |
+-------+-----------+----------------------+---------+----------+-------+
| 1459  | 127.0.0.1 | admin.$cmd.aggregate | command | 0 ms     | ""    |
+-------+-----------+----------------------+---------+----------+-------+

L’affichage se fait donc en tableau, chaque requête est sur une ligne
Les infos importantes se trouvent avant la requête ce qui vous permet de bien les voir même si la requête est longue
Comme vous pouvez le voir dans le coin en haut à droite, l’affichage est automatiquement rafraîchi toutes les 5 secondes

Cet affichage m’a permit de voir que les requêtes de recherche restaient plusieurs minutes ici à s’empiler jusqu’à faire crash le serveur Mongo
Je n’avais jamais réussi à voir clairement ce problème avec db.currentOp()
Donc je suis vraiment content de ce script et je voulais le partager ici pour ne pas le perdre 🙂

Conclusion

Pour finir je veux redire que Mongo est sans doute un système très performant et qui a ses avantages
Mais personnellement, je sais qu’on a eu des soucis sur des choses qui semblent basiques, comme protéger l’accès à la base de donnée ou afficher l’état des requêtes en cours
Ce sont des choses qui sont intuitives sur une base MySQL et qui semble avancées sur MongoDB, ce que je trouve dommage car je pense que tout le monde en a besoin

Après encore une fois c’est un outil que je maîtrise beaucoup moins que MySQL, et peut être que ceux qui vont la transition dans l’autre sens ont le même genre de problèmes

En tout cas l’important est de trouver des solutions, et vous en avez une ici 🙂

A lire également