/** * Copyright (C) 2009 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects for * all of the code used other than as permitted herein. If you modify file(s) * with this exception, you may extend this exception to your version of the * file(s), but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. */ #include "mongo/platform/basic.h" #include "mongo/bson/bsonobjbuilder.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_session.h" #include "mongo/db/client.h" #include "mongo/db/commands.h" #include "mongo/db/curop.h" #include "mongo/db/dbwebserver.h" #include "mongo/db/matcher/expression_parser.h" #include "mongo/db/matcher/extensions_callback_disallow_extensions.h" #include "mongo/db/operation_context.h" #include "mongo/db/service_context.h" #include "mongo/db/stats/fill_locker_info.h" #include "mongo/rpc/metadata/client_metadata.h" #include "mongo/rpc/metadata/client_metadata_ismaster.h" #include "mongo/util/mongoutils/html.h" #include "mongo/util/stringutils.h" namespace mongo { using std::unique_ptr; using std::string; namespace { class ClientListPlugin : public WebStatusPlugin { public: ClientListPlugin() : WebStatusPlugin("clients", 20) {} virtual void init() {} virtual void run(OperationContext* opCtx, std::stringstream& ss) { using namespace html; ss << "\n"; ss << "" << th(a("", "Connections to the database, both internal and external.", "Client")) << th(a("http://dochub.mongodb.org/core/viewingandterminatingcurrentoperation", "", "OpId")) << "" << "" << "" << "" << th(a("http://dochub.mongodb.org/core/whatisanamespace", "", "Namespace")) << "" << "" << "" << "" << "\n"; _processAllClients(opCtx->getClient()->getServiceContext(), ss); ss << "
LockingWaitingSecsRunningOpQueryclientmsgprogress
\n"; } private: static void _processAllClients(ServiceContext* service, std::stringstream& ss) { using namespace html; for (ServiceContext::LockedClientsCursor cursor(service); Client* client = cursor.next();) { invariant(client); // Make the client stable stdx::lock_guard lk(*client); const OperationContext* opCtx = client->getOperationContext(); if (!opCtx) continue; CurOp* curOp = CurOp::get(opCtx); if (!curOp) continue; ss << "" << client->desc() << ""; tablecell(ss, opCtx->getOpID()); tablecell(ss, true); // LockState { Locker::LockerInfo lockerInfo; opCtx->lockState()->getLockerInfo(&lockerInfo); BSONObjBuilder lockerInfoBuilder; fillLockerInfo(lockerInfo, lockerInfoBuilder); tablecell(ss, lockerInfoBuilder.obj()); } tablecell(ss, curOp->elapsedSeconds()); tablecell(ss, curOp->getNetworkOp()); tablecell(ss, html::escape(curOp->getNS())); if (curOp->haveQuery()) { tablecell(ss, html::escape(curOp->query().toString())); } else { tablecell(ss, ""); } tablecell(ss, client->clientAddress(true /*includePort*/)); tablecell(ss, curOp->getMessage()); tablecell(ss, curOp->getProgressMeter().toString()); ss << "\n"; } } } clientListPlugin; } // namespace } // namespace mongo