MongoDB记录所有查询


169

问题很简单,就这么简单...如何在mongodb中的“可尾”的日志文件中记录所有查询?

我努力了:

  • 设置配置级别
  • 设置慢速ms参数启动
  • -vv选项的mongod

/var/log/mongodb/mongodb.log继续仅显示当前活动连接数...


mongod -vv为我工作
fguillen

Answers:


259

您可以记录所有查询:

$ 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()

资料来源:http : //docs.mongodb.org/manual/reference/method/db.setProfilingLevel/

db.setProfilingLevel(2) 表示“记录所有操作”。


3
乍一看,这似乎比接受的答案更好。
Ehtesh Choudhury 2014年

2
考虑到这些问题要求提供一个可尾的日志文件,这并不更好,但是绝对有用,在您无权访问日志文件的情况下,只有mongo shell,就像带我到这里的那个一样:)
inolasco

11
我尝试将性能分析级别设置为2,但我还需要将第二个参数设置为-1,例如db.setProfilingLevel(2,-1)
andresigualada

4
对于那些感兴趣的日志,文档指出:mongod将数据库探查器的输出写入system.profile集合。
totymedli

5
db.system.profile.find().pretty()什么都不给我
node_saini

84

我最终通过像这样启动mongod来解决了这个问题(锤子又丑陋,是的,但是在开发环境中工作):

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

这将启用性能分析并将“慢速查询”的阈值设置为1ms,从而导致所有查询都作为“慢速查询”记录到文件中:

/var/log/mongodb/mongodb.log

现在,我使用以下命令获得连续的日志输出:

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

日志示例:

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
这应该等同于在中添加profile=1slowms=1/etc/mongodb.conf吗?
Andrew Magee 2014年

我找不到/var/log/mongodb/mongodb.log,但它正在控制台中登录,这是我所需要的。谢谢
auhuman 2014年

4
你可以只添加--profile=2/etc/mongodb.conf根据官方蒙戈文档,任何所有的操作都会被记录下来。
toske 2015年

1
@auhuman在哪里写“ tail -f /var/log/mongodb/mongodb.log”命令?
Half Blood Prince

5
无需重启,您可以简单地使用db.setProfilingLevel(level,slowms)。例如:db.setProfilingLevel(2,1)将级别设置为2,将慢速查询阈值设置为1ms。
Abhishek Gupta


25

MongoDB具有概要分析功能。日志记录发生在system.profile集合中。可以从以下位置查看日志:

db.system.profile.find()

有3个日志记录级别():

  • 级别0-探查器已关闭,不收集任何数据。mongod对其日志的写操作总是长于slowOpThresholdMs阈值。这是默认的探查器级别。
  • 级别1-收集性能分析数据仅用于慢速操作。默认情况下,慢速操作是指那些慢于100毫秒的操作。您可以使用slowOpThresholdMs运行时选项或setParameter命令修改“慢速”操作的阈值。有关更多信息,请参见指定慢速操作阈值部分。
  • 级别2-收集所有数据库操作的分析数据。

要查看数据库正在运行的概要分析级别,请使用

db.getProfilingLevel()

并查看状态

db.getProfilingStatus()

要更改分析状态,请使用以下命令

db.setProfilingLevel(level, milliseconds)

其中,level是指概要分析级别,milliseconds是需要记录查询持续时间的毫秒数。要关闭日志记录,请使用

db.setProfilingLevel(0)

在系统配置文件集合中查找所有耗时超过一秒(按时间戳降序排列)的查询将为

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

1
根据该文件,日志级别0确实不是意味着“无记录”,但它记录查询速度慢:“分析器是关闭的,不收集任何数据的mongod总是比slowOpThresholdMs门槛,其日志写入操作更长的时间。” src:docs.mongodb.com/v3.2/tutorial/manage-the-database-profiler/…–
kayn

23

我制作了一个命令行工具来激活事件探查器活动,并以“可尾”的方式查看日志:“ mongotail”

但是更有趣的功能(也像一样tail)是使用选项查看“实时”的变化-f,并偶尔过滤结果grep以查找特定的操作。

请参阅以下文档中的文档和安装说明:https : //github.com/mrsarm/mongotail


2
这是对OP的最完整的回应。尤其是 关于“可尾”的要求。
路加福音W

11

使用设置分析级别后db.setProfilingLevel(2)

下面的命令将打印最后执行的查询。
您也可以更改limit(5)以查看更少/更多的查询。
$ nin-将过滤掉配置文件和索引查询
此外,将查询投影{'query':1}仅用于查看查询字段

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

仅具有查询投影的日志

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


7

探查器数据将写入数据库中的集合,而不是文件中。参见http://docs.mongodb.org/manual/tutorial/manage-the-database-profiler/

我建议使用10gen的MMS服务,并在其中输入开发配置文件数据,您可以在其中对UI进行过滤和排序。


1
是的,在激活2级分析后,将集合添加到数据库中。但是,每次执行调试时都必须重新加载gui或运行命令是一天结束时的PITA。这就是为什么我想要一个可尾的日志文件。
若昂罗沙达席尔瓦


4

将profilinglevel设置为2是另一个记录所有查询的选项。


3

我建议检查mongosniff。该工具可以完成您想要做的所有事情。尤其是,它可以通过侦听所有mongo相关通信的网络接口来帮助诊断大型mongo系统的问题以及如何路由查询以及查询的来源。

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


根据该页面,它仅在UNIX环境下有效,而我在Windows的bin目录中没有此功能。是否有任何推荐的Windows Equiv?
2014年

您是在远程Windows服务器(天蓝色云等)上还是在本地PC上运行?如果全部在本地,wireshark将绰绰有余。要在Windows上安装它,您将需要构建mongosniff.exe,该文件未公开。您遵循linux的说明,但是需要安装winpcap的开发版本。
Daniel Williams

谢谢回复。我最终能够从mongo profiler中获取所需的信息,但是如果再次出现更严重的问题,我将把Wireshk放在口袋里。
2014年

1

我编写了一个脚本,该脚本将在查询进入时实时打印出system.profile日志。您需要先启用日志,如其他答案所述。我之所以需要它,是因为我使用的是Windows Subsystem for Linux,但对于它而言,它的尾巴仍然无法使用。

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


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

然后

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

5
欢迎使用Stack Overflow!尽管此代码可以解决问题,但提供说明确实有助于提高您的帖子质量。
Shree

1

这是很久以前问过的,但这仍然可以帮助某人:

MongoDB探查器将所有查询记录在有上限的集合system.profile中。参见:数据库分析器

  1. 使用--profile=2启用日志记录所有查询的选项 启动mongod实例,或者如果mongod实例已经在运行,则从mongoshell中db.setProfilingLevel(2)选择数据库后运行。(可以通过验证 db.getProfilingLevel(),它应该返回2
  2. 在此之后,我创建了一个脚本,该脚本利用mongodb的可拖尾游标来拖尾此system.profile集合,并将条目写入文件中。要查看日志,我只需要拖尾它:tail -f ../logs/mongologs.txt。该脚本可以在后台启动,并将所有操作记录在文件中的db上。

我的system.profile集合的可尾游标代码在nodejs中;它记录所有操作以及在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'))
    })

});

}

对于使用pymongo的python中的可尾光标,请参考以下代码,该代码过滤MyCollection并仅执行插入操作:

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)

注意:可尾游标仅适用于上限集合。它不能用于直接记录对集合的操作,而要使用filter:'ns': 'MyDb.MyCollection'

注意:我知道上面的nodejs和python代码对某些人可能没有太大帮助。我刚刚提供了代码以供参考。

使用此链接在您的语言/驱动程序选择中查找可尾光标的文档。Mongodb Drivers

我在此logrotate之后添加的另一个功能。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.