From 9e4087883d0acb3bbbdf8c8b2b175e8b8da511c1 Mon Sep 17 00:00:00 2001 From: Eliot Horowitz Date: Sun, 8 May 2011 00:53:07 -0400 Subject: [PATCH] put fields into system.profile, not a big string SERVER-3061 --- db/client.cpp | 59 +++++++++++++++++++++++++++++++---------- db/curop.h | 4 +++ db/instance.cpp | 2 +- db/introspect.cpp | 5 +++- db/introspect.h | 2 +- shell/mongo_vstudio.cpp | 27 ++++++++++++++++++- shell/utils.js | 27 ++++++++++++++++++- 7 files changed, 107 insertions(+), 19 deletions(-) diff --git a/db/client.cpp b/db/client.cpp index ac7c54d1db5..7989ef553e2 100644 --- a/db/client.cpp +++ b/db/client.cpp @@ -551,7 +551,7 @@ namespace mongo { } -#define OPDEBUG_HELP(x) if( x ) s << " " #x ":" << (x) +#define OPDEBUG_TOSTRING_HELP(x) if( x ) s << " " #x ":" << (x) string OpDebug::toString() const { StringBuilder s( ns.size() + 64 ); if ( iscommand ) @@ -573,19 +573,19 @@ namespace mongo { updateobj.toString( s , false , true ); } - OPDEBUG_HELP( cursorid ); - OPDEBUG_HELP( ntoreturn ); - OPDEBUG_HELP( ntoskip ); - OPDEBUG_HELP( exhaust ); + OPDEBUG_TOSTRING_HELP( cursorid ); + OPDEBUG_TOSTRING_HELP( ntoreturn ); + OPDEBUG_TOSTRING_HELP( ntoskip ); + OPDEBUG_TOSTRING_HELP( exhaust ); - OPDEBUG_HELP( nscanned ); - OPDEBUG_HELP( idhack ); - OPDEBUG_HELP( scanAndOrder ); - OPDEBUG_HELP( moved ); - OPDEBUG_HELP( fastmod ); - OPDEBUG_HELP( fastmodinsert ); - OPDEBUG_HELP( upsert ); - OPDEBUG_HELP( keyUpdates ); + OPDEBUG_TOSTRING_HELP( nscanned ); + OPDEBUG_TOSTRING_HELP( idhack ); + OPDEBUG_TOSTRING_HELP( scanAndOrder ); + OPDEBUG_TOSTRING_HELP( moved ); + OPDEBUG_TOSTRING_HELP( fastmod ); + OPDEBUG_TOSTRING_HELP( fastmodinsert ); + OPDEBUG_TOSTRING_HELP( upsert ); + OPDEBUG_TOSTRING_HELP( keyUpdates ); if ( extra.len() ) s << " " << extra.str(); @@ -596,7 +596,7 @@ namespace mongo { s << " code:" << exceptionInfo.code; } - OPDEBUG_HELP( nreturned ); + OPDEBUG_TOSTRING_HELP( nreturned ); if ( responseLength ) s << " reslen:" << responseLength; s << " " << executionTime << "ms"; @@ -604,6 +604,37 @@ namespace mongo { return s.str(); } +#define OPDEBUG_APPEND_NUMBER(x) if( x ) b.append( #x , (x) ) +#define OPDEBUG_APPEND_BOOL(x) if( x ) b.appendBool( #x , (x) ) + void OpDebug::append( BSONObjBuilder& b ) const { + b.append( "op" , iscommand ? "command" : opToString( op ) ); + b.append( "ns" , ns.toString() ); + if ( ! query.isEmpty() ) + b.append( iscommand ? "command" : "query" , query ); + if ( ! updateobj.isEmpty() ) + b.append( "updateobj" , "updateobj" ); + + OPDEBUG_APPEND_NUMBER( cursorid ); + OPDEBUG_APPEND_NUMBER( ntoreturn ); + OPDEBUG_APPEND_NUMBER( ntoskip ); + OPDEBUG_APPEND_BOOL( exhaust ); + OPDEBUG_APPEND_NUMBER( nscanned ); + OPDEBUG_APPEND_BOOL( idhack ); + OPDEBUG_APPEND_BOOL( scanAndOrder ); + OPDEBUG_APPEND_BOOL( moved ); + OPDEBUG_APPEND_BOOL( fastmod ); + OPDEBUG_APPEND_BOOL( fastmodinsert ); + OPDEBUG_APPEND_BOOL( upsert ); + OPDEBUG_APPEND_NUMBER( keyUpdates ); + + if ( ! exceptionInfo.empty() ) + exceptionInfo.append( b , "exception" , "exceptionCode" ); + + OPDEBUG_APPEND_NUMBER( nreturned ); + OPDEBUG_APPEND_NUMBER( responseLength ); + b.append( "millis" , executionTime ); + + } } diff --git a/db/curop.h b/db/curop.h index 86c7a221bf4..5627ff77afe 100644 --- a/db/curop.h +++ b/db/curop.h @@ -35,8 +35,12 @@ namespace mongo { OpDebug() : ns(""){ reset(); } void reset(); + string toString() const; + void append( BSONObjBuilder& b ) const; + // ------------------- + StringBuilder extra; // weird things we need to fix later // basic options diff --git a/db/instance.cpp b/db/instance.cpp index 79ee7372eb6..60a80cdad96 100644 --- a/db/instance.cpp +++ b/db/instance.cpp @@ -373,7 +373,7 @@ namespace mongo { writelock lk; if ( dbHolder.isLoaded( nsToDatabase( currentOp.getNS() ) , dbpath ) ) { Client::Context cx( currentOp.getNS() ); - profile(c , currentOp, ms); + profile(c , currentOp ); } else { mongo::log() << "note: not profiling because db went away - probably a close on: " << currentOp.getNS() << endl; diff --git a/db/introspect.cpp b/db/introspect.cpp index 2b2a4683503..b81ed1c8924 100644 --- a/db/introspect.cpp +++ b/db/introspect.cpp @@ -29,17 +29,20 @@ namespace mongo { BufBuilder profileBufBuilder; // reused, instead of allocated every time - avoids a malloc/free cycle - void profile( const Client& c , CurOp& currentOp, int millis) { + void profile( const Client& c , CurOp& currentOp ) { assertInWriteLock(); profileBufBuilder.reset(); BSONObjBuilder b(profileBufBuilder); b.appendDate("ts", jsTime()); + currentOp.debug().append( b ); + /* const string info = currentOp.debug().toString(); b.append("info", info); b.append("millis", (double) millis); if ( currentOp.getNS() ) b.append( "ns" , currentOp.getNS() ); + */ b.append("client", c.clientAddress() ); BSONObj p = b.done(); diff --git a/db/introspect.h b/db/introspect.h index e3dfcf65e44..209eeacab7c 100644 --- a/db/introspect.h +++ b/db/introspect.h @@ -29,6 +29,6 @@ namespace mongo { do when database->profile is set */ - void profile( const Client& c , CurOp& currentOp, int millis); + void profile( const Client& c , CurOp& currentOp ); } // namespace mongo diff --git a/shell/mongo_vstudio.cpp b/shell/mongo_vstudio.cpp index 416afe51deb..7e8be9ad07d 100644 --- a/shell/mongo_vstudio.cpp +++ b/shell/mongo_vstudio.cpp @@ -1096,7 +1096,32 @@ const StringData _jscode_raw_utils = "}\n" "else {\n" "print();\n" -"db.system.profile.find({ millis: { $gt: 0} }).sort({ $natural: -1 }).limit(5).forEach(function (x) { print(\"\" + x.millis + \"ms \" + String(x.ts).substring(0, 24)); print(x.info); print(\"\\n\"); })\n" +"db.system.profile.find({ millis: { $gt: 0} }).sort({ $natural: -1 }).limit(5).forEach(\n" +"function (x) {\n" +"print(\"\" + x.op + \"\\t\" + x.ns + \" \" + x.millis + \"ms \" + String(x.ts).substring(0, 24));\n" +"var l = \"\";\n" +"for ( var z in x ){\n" +"if ( z == \"op\" || z == \"ns\" || z == \"millis\" || z == \"ts\" )\n" +"continue;\n" +"\n" +"var val = x[z];\n" +"var mytype = typeof(val);\n" +"\n" +"if ( mytype == \"string\" ||\n" +"mytype == \"number\" )\n" +"l += z + \":\" + val + \" \";\n" +"else if ( mytype == \"object\" )\n" +"l += z + \":\" + tojson(val ) + \" \";\n" +"else if ( mytype == \"boolean\" )\n" +"l += z + \" \";\n" +"else\n" +"l += z + \":\" + val + \" \";\n" +"\n" +"}\n" +"print( l );\n" +"print(\"\\n\");\n" +"}\n" +")\n" "}\n" "return \"\";\n" "}\n" diff --git a/shell/utils.js b/shell/utils.js index a23c6755247..dd610dcaea2 100644 --- a/shell/utils.js +++ b/shell/utils.js @@ -1091,7 +1091,32 @@ shellHelper.show = function (what) { } else { print(); - db.system.profile.find({ millis: { $gt: 0} }).sort({ $natural: -1 }).limit(5).forEach(function (x) { print("" + x.millis + "ms " + String(x.ts).substring(0, 24)); print(x.info); print("\n"); }) + db.system.profile.find({ millis: { $gt: 0} }).sort({ $natural: -1 }).limit(5).forEach( + function (x) { + print("" + x.op + "\t" + x.ns + " " + x.millis + "ms " + String(x.ts).substring(0, 24)); + var l = ""; + for ( var z in x ){ + if ( z == "op" || z == "ns" || z == "millis" || z == "ts" ) + continue; + + var val = x[z]; + var mytype = typeof(val); + + if ( mytype == "string" || + mytype == "number" ) + l += z + ":" + val + " "; + else if ( mytype == "object" ) + l += z + ":" + tojson(val ) + " "; + else if ( mytype == "boolean" ) + l += z + " "; + else + l += z + ":" + val + " "; + + } + print( l ); + print("\n"); + } + ) } return ""; }