void CatalogManagerReplicaSet::logChange(const string& clientAddress,
                                         const string& what,
                                         const string& ns,
                                         const BSONObj& detail) {
    if (_changeLogCollectionCreated.load() == 0) {
        BSONObj createCmd = BSON("create" << ChangelogType::ConfigNS << "capped" << true << "size"
                                          << kChangeLogCollectionSize);
        auto result = _runConfigServerCommandWithNotMasterRetries("config", createCmd);
        if (!result.isOK()) {
            LOG(1) << "couldn't create changelog collection: " << causedBy(result.getStatus());
            return;
        }

        Status commandStatus = Command::getStatusFromCommandResult(result.getValue());
        if (commandStatus.isOK() || commandStatus == ErrorCodes::NamespaceExists) {
            _changeLogCollectionCreated.store(1);
        } else {
            LOG(1) << "couldn't create changelog collection: " << causedBy(commandStatus);
            return;
        }
    }

    Date_t now = grid.shardRegistry()->getExecutor()->now();
    std::string hostName = grid.shardRegistry()->getNetwork()->getHostName();
    const string changeID = str::stream() << hostName << "-" << now.toString() << "-" << OID::gen();

    ChangelogType changeLog;
    changeLog.setChangeID(changeID);
    changeLog.setServer(hostName);
    changeLog.setClientAddr(clientAddress);
    changeLog.setTime(now);
    changeLog.setNS(ns);
    changeLog.setWhat(what);
    changeLog.setDetails(detail);

    BSONObj changeLogBSON = changeLog.toBSON();
    log() << "about to log metadata event: " << changeLogBSON;

    Status result = insert(ChangelogType::ConfigNS, changeLogBSON, NULL);
    if (!result.isOK()) {
        warning() << "Error encountered while logging config change with ID " << changeID << ": "
                  << result;
    }
}
    Status logConfigChange(const ConnectionString& configLoc,
                           const string& clientHost,
                           const string& ns,
                           const string& description,
                           const BSONObj& details)
    {
        //
        // The code for writing to the changelog collection exists elsewhere - we duplicate here to
        // avoid dependency issues.
        // TODO: Merge again once config.cpp is cleaned up.
        //

        string changeID = stream() << getHostNameCached() << "-" << terseCurrentTime() << "-"
                                   << OID::gen();

        ChangelogType changelog;
        changelog.setChangeID(changeID);
        changelog.setServer(getHostNameCached());
        changelog.setClientAddr(clientHost == "" ? "N/A" : clientHost);
        changelog.setTime(jsTime());
        changelog.setWhat(description);
        changelog.setNS(ns);
        changelog.setDetails(details);

        log() << "about to log new metadata event: " << changelog.toBSON() << endl;

        scoped_ptr<ScopedDbConnection> connPtr;

        try {
            connPtr.reset(new ScopedDbConnection(configLoc, 30));
            ScopedDbConnection& conn = *connPtr;

            // TODO: better way here
            static bool createdCapped = false;
            if (!createdCapped) {

                try {
                    conn->createCollection(ChangelogType::ConfigNS, 1024 * 1024 * 10, true);
                }
                catch (const DBException& e) {
                    // don't care, someone else may have done this for us
                    // if there's still a problem, caught in outer try
                    LOG(1) << "couldn't create the changelog, continuing " << e << endl;
                }

                createdCapped = true;
            }
            connPtr->done();
        }
        catch (const DBException& e) {
            // if we got here, it means the config change is only in the log,
            // it didn't make it to config.changelog
            log() << "not logging config change: " << changeID << causedBy(e) << endl;
            return e.toStatus();
        }

        Status result = clusterInsert( ChangelogType::ConfigNS,
                                       changelog.toBSON(),
                                       WriteConcernOptions::AllConfigs,
                                       NULL );

        if ( !result.isOK() ) {
            return Status( result.code(), str::stream() << "failed to write to changelog: "
                                                        << result.reason() );
        }

        return result;
    }