MongoDB enregistre toutes les requêtes


169

La question est aussi basique que simple ... Comment consigner toutes les requêtes dans un fichier journal capable de "queue" dans mongodb?

J'ai essayé:

  • définition du niveau de profilage
  • réglage du paramètre ms lent démarrage
  • mongod avec l'option -vv

Le fichier /var/log/mongodb/mongodb.log continue d'afficher uniquement le nombre actuel de connexions actives ...


mongod -vvtravaillé pour moi
fguillen

Réponses:


259

Vous pouvez enregistrer toutes les requêtes:

$ mongo
MongoDB shell version: 2.4.9
connecting to: test
> use myDb
switched to db myDb
> db.getProfilingLevel()
0
> db.setProfilingLevel(2)
{ "was" : 0, "slowms" : 1, "ok" : 1 }
> db.getProfilingLevel()
2
> db.system.profile.find().pretty()

Source: http://docs.mongodb.org/manual/reference/method/db.setProfilingLevel/

db.setProfilingLevel(2) signifie «consigner toutes les opérations».


3
En un coup d'œil, il semble que ce soit une meilleure réponse que la réponse acceptée.
Ehtesh Choudhury

2
Pas mieux, étant donné que les questions demandent un fichier journal disponible, mais certainement utile, dans les cas où vous n'avez pas accès aux fichiers journaux, uniquement le shell mongo, comme celui qui m'a amené ici :)
inolasco

11
J'ai essayé de définir le niveau de profilage sur 2 mais j'avais également besoin de définir le deuxième paramètre sur -1, commedb.setProfilingLevel(2,-1)
andresigualada

4
Pour ceux qui s'intéressent à la destination des journaux, le document déclare: mongod écrit la sortie du profileur de base de données dans la system.profilecollection.
totymedli

5
db.system.profile.find().pretty()ne donne rien pour moi
node_saini

84

J'ai fini par résoudre cela en démarrant mongod comme ça (martelé et moche, ouais ... mais fonctionne pour l'environnement de développement):

mongod --profile=1 --slowms=1 &

Cela active le profilage et définit le seuil des «requêtes lentes» sur 1 ms, ce qui entraîne la journalisation de toutes les requêtes en tant que «requêtes lentes» dans le fichier:

/var/log/mongodb/mongodb.log

Maintenant, j'obtiens des sorties de journal continues en utilisant la commande:

tail -f /var/log/mongodb/mongodb.log

Un exemple de journal:

Mon Mar  4 15:02:55 [conn1] query dendro.quads query: { graph: "u:http://example.org/people" } ntoreturn:0 ntoskip:0 nscanned:6 keyUpdates:0 locks(micros) r:73163 nreturned:6 reslen:9884 88ms

6
Cela devrait-il être équivalent à ajouter des lignes profile=1et ? slowms=1/etc/mongodb.conf
Andrew Magee

Je n'ai pas pu trouver /var/log/mongodb/mongodb.log mais il se connectait dans la console, ce dont j'avais besoin. Merci
auhuman

4
Vous pouvez simplement ajouter --profile=2à /etc/mongodb.confselon docs officiels mongo, toutes toutes les opérations seront enregistrées.
toske

1
@auhuman Où écrire la commande "tail -f /var/log/mongodb/mongodb.log" ??
Half Blood Prince

5
Pas besoin de redémarrer, vous pouvez simplement l'utiliser db.setProfilingLevel(level,slowms). Par exemple: db.setProfilingLevel(2,1)définira le niveau sur 2 et le seuil de requête lente sur 1 ms.
Abhishek Gupta


25

MongoDBa une fonction sophistiquée de profilage. La journalisation se produit dans la system.profilecollection. Les journaux peuvent être consultés à partir de:

db.system.profile.find()

Il existe 3 niveaux de journalisation ( source ):

  • Niveau 0 - le profileur est désactivé, ne collecte aucune donnée. mongod écrit toujours des opérations plus longues que le seuil slowOpThresholdMs dans son journal. Il s'agit du niveau de profileur par défaut.
  • Niveau 1 - collecte les données de profilage pour les opérations lentes uniquement. Par défaut, les opérations lentes sont celles plus lentes que 100 millisecondes. Vous pouvez modifier le seuil pour les opérations «lentes» avec l'option d'exécution slowOpThresholdMs ou la commande setParameter. Consultez la section Spécifier le seuil pour les opérations lentes pour plus d'informations.
  • Niveau 2 - collecte les données de profilage pour toutes les opérations de base de données.

Pour voir le niveau de profilage dans lequel la base de données s'exécute, utilisez

db.getProfilingLevel()

et pour voir le statut

db.getProfilingStatus()

Pour modifier l'état du profilage, utilisez la commande

db.setProfilingLevel(level, milliseconds)

levelfait référence au niveau de profilage et millisecondscorrespond à la durée en ms pendant laquelle les requêtes doivent être enregistrées. Pour désactiver la journalisation, utilisez

db.setProfilingLevel(0)

La requête à rechercher dans la collection de profils système pour toutes les requêtes qui ont duré plus d'une seconde, classées par horodatage décroissant, sera

db.system.profile.find( { millis : { $gt:1000 } } ).sort( { ts : -1 } )

1
Selon la documentation, Loglevel 0 ne signifie pas "pas de journalisation" mais il enregistre les requêtes lentes: "le profileur est désactivé, ne collecte aucune donnée. Mongod écrit toujours des opérations plus longues que le seuil slowOpThresholdMs dans son journal." src: docs.mongodb.com/v3.2/tutorial/manage-the-database-profiler/…
kayn

23

J'ai créé un outil en ligne de commande pour activer l'activité du profileur et voir les logs de manière "tail" : "mongotail" .

Mais la fonctionnalité la plus intéressante (comme tail) est de voir les changements en "temps réel" avec l' -foption, et de filtrer occasionnellement le résultat avec greppour trouver une opération particulière.

Voir la documentation et les instructions d'installation sur: https://github.com/mrsarm/mongotail


2
c'est la réponse la plus complète au PO. esp. concernant l'exigence «adaptable».
Luke W

11

Une fois le niveau de profilage défini, utilisez db.setProfilingLevel(2).

La commande ci-dessous imprimera la dernière requête exécutée.
Vous pouvez également modifier la limite (5) pour voir moins / plus de requêtes.
$ nin - filtrera les requêtes de profil et d'indexation
. Utilisez également la projection de requête {'query': 1} pour afficher uniquement le champ de requête

db.system.profile.find(
{ 
    ns: { 
        $nin : ['meteor.system.profile','meteor.system.indexes']
    }
} 
).limit(5).sort( { ts : -1 } ).pretty()

Journaux avec uniquement la projection de requête

db.system.profile.find(
{ 
    ns: { 
        $nin : ['meteor.system.profile','meteor.system.indexes']
    }
},
{'query':1}
).limit(5).sort( { ts : -1 } ).pretty()

10

si vous souhaitez que les requêtes soient enregistrées dans le fichier journal mongodb, vous devez définir à la fois le niveau de journalisation et le profilage, comme par exemple:

db.setLogLevel(1)
db.setProfilingLevel(2)

(voir https://docs.mongodb.com/manual/reference/method/db.setLogLevel )

Si vous ne définissez que le profilage, les requêtes ne sont pas enregistrées dans un fichier, vous ne pouvez donc l'obtenir qu'à partir de

db.system.profile.find().pretty()

7

Les données du profileur sont écrites dans une collection de votre base de données, pas dans un fichier. Voir http://docs.mongodb.org/manual/tutorial/manage-the-database-profiler/

Je recommanderais d'utiliser le service MMS de 10gen et les données du profileur de développement de flux là-bas, où vous pouvez les filtrer et les trier dans l'interface utilisateur.


1
Oui, après l'activation du profilage de niveau 2, une collection est ajoutée à la base de données. Cependant, devoir recharger une interface graphique ou exécuter une commande à chaque fois que j'effectue un débogage est un PITA à la fin de la journée ... C'est pourquoi je voulais un fichier journal disponible.
João Rocha da Silva


4

La définition de profilinglevel sur 2 est une autre option pour consigner toutes les requêtes.


3

Je recommande de vérifier mongosniff. Cet outil peut faire tout ce que vous voulez et plus encore. En particulier, il peut aider à diagnostiquer les problèmes avec les systèmes mongo à plus grande échelle, la façon dont les requêtes sont acheminées et leur provenance, car il fonctionne en écoutant votre interface réseau pour toutes les communications liées à mongo.

http://docs.mongodb.org/v2.2/reference/mongosniff/


Selon cette page, cela ne fonctionne que dans les environnements UNIX, et je ne l'ai pas dans mon répertoire bin dans Windows. Des fenêtres recommandées equiv?
propagée le

Exécutez-vous sur un serveur Windows distant (cloud Azure, etc.) ou localement sur votre PC? Si tout est localement, Wirehark sera plus que suffisant. Pour l'installer sous Windows, vous devrez créer mongosniff.exe qui est un peu non documenté. Vous suivez les instructions de Linux mais vous devez installer la version de développement de winpcap.
Daniel Williams

Merci pour la réponse. J'ai fini par être en mesure d'obtenir les informations dont j'avais besoin du profileur mongo, mais je garderai WireShark dans ma poche si quelque chose de plus grave se produit à nouveau.
propagée le

1

J'ai écrit un script qui imprimera le journal system.profile en temps réel lorsque les requêtes arrivent. Vous devez d'abord activer la journalisation comme indiqué dans d'autres réponses. J'en avais besoin parce que j'utilise le sous-système Windows pour Linux, pour lequel la queue ne fonctionne toujours pas.

https://github.com/dtruel/mongo-live-logger


1
db.adminCommand( { getLog: "*" } )

ensuite

db.adminCommand( { getLog : "global" } )

5
Bienvenue dans Stack Overflow! Bien que ce code puisse résoudre la question, inclure une explication contribue vraiment à améliorer la qualité de votre message.
Shree

1

Cela a été demandé il y a longtemps, mais cela peut encore aider quelqu'un:

Le profileur MongoDB enregistre toutes les requêtes dans le système de collecte plafonné . Voir ceci: profileur de base de données

  1. Démarrez l'instance mongod avec l' --profile=2option qui permet de journaliser toutes les requêtes OU si les instances mongod sont déjà en cours d'exécution, à partir de mongoshell, exécutez db.setProfilingLevel(2)après avoir sélectionné la base de données. (il peut être vérifié par db.getProfilingLevel(), qui devrait revenir 2)
  2. Après cela, j'ai créé un script qui utilise le curseur tailable de mongodb pour suivre cette collection system.profile et écrire les entrées dans un fichier. Pour afficher les journaux que j'ai juste besoin de la queue , il: tail -f ../logs/mongologs.txt. Ce script peut être lancé en arrière-plan et il enregistrera toutes les opérations sur la base de données dans le fichier.

Mon code pour le curseur disponible pour la collection system.profile est dans nodejs; il enregistre toutes les opérations ainsi que les requêtes se produisant dans chaque collection de MyDb:

const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const fs = require('fs');
const file = '../logs/mongologs'
// Connection URL
const url = 'mongodb://localhost:27017';

// Database Name
const dbName = 'MyDb';
//Mongodb connection

MongoClient.connect(url, function (err, client) {
   assert.equal(null, err);
   const db = client.db(dbName);
   listen(db, {})
});

function listen(db, conditions) {
var filter = { ns: { $ne: 'MyDb.system.profile' } }; //filter for query
//e.g. if we need to log only insert queries, use {op:'insert'}
//e.g. if we need to log operation on only 'MyCollection' collection, use {ns: 'MyDb.MyCollection'}
//we can give a lot of filters, print and check the 'document' variable below

// set MongoDB cursor options
var cursorOptions = {
    tailable: true,
    awaitdata: true,
    numberOfRetries: -1
};

// create stream and listen
var stream = db.collection('system.profile').find(filter, cursorOptions).stream();

// call the callback
stream.on('data', function (document) {
    //this will run on every operation/query done on our database
    //print 'document' to check the keys based on which we can filter
    //delete data which we dont need in our log file

    delete document.execStats;
    delete document.keysExamined;
    //-----
    //-----

    //append the log generated in our log file which can be tailed from command line
    fs.appendFile(file, JSON.stringify(document) + '\n', function (err) {
        if (err) (console.log('err'))
    })

});

}

Pour le curseur disponible en python utilisant pymongo, reportez-vous au code suivant qui filtre pour MyCollection et insère uniquement l'opération:

import pymongo
import time
client = pymongo.MongoClient()
oplog = client.MyDb.system.profile
first = oplog.find().sort('$natural', pymongo.ASCENDING).limit(-1).next()

ts = first['ts']
while True:
    cursor = oplog.find({'ts': {'$gt': ts}, 'ns': 'MyDb.MyCollection', 'op': 'insert'},
                        cursor_type=pymongo.CursorType.TAILABLE_AWAIT)
    while cursor.alive:
        for doc in cursor:
            ts = doc['ts']
            print(doc)
            print('\n')
        time.sleep(1)

Remarque: le curseur disponible ne fonctionne qu'avec les collections plafonnées. Il ne peut pas être utilisé pour enregistrer directement des opérations sur une collection, utilisez plutôt un filtre:'ns': 'MyDb.MyCollection'

Remarque: je comprends que les nodejs et le code python ci-dessus peuvent ne pas être d'une grande aide pour certains. Je viens de fournir les codes pour référence.

Utilisez ce lien pour trouver de la documentation sur le curseur disponible dans votre langue / choix de pilote Mongodb Drivers

Une autre fonctionnalité que j'ai ajoutée après ce logrotate .


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.