All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog2.system.stats.mongo.MongoProbe Maven / Gradle / Ivy

There is a newer version: 6.0.1
Show newest version
/*
 * Copyright (C) 2020 Graylog, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the Server Side Public License, version 1,
 * as published by MongoDB, Inc.
 *
 * 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
 * Server Side Public License for more details.
 *
 * You should have received a copy of the Server Side Public License
 * along with this program. If not, see
 * .
 */
package org.graylog2.system.stats.mongo;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.net.HostAndPort;
import com.mongodb.BasicDBObject;
import com.mongodb.CommandResult;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
import com.mongodb.connection.ServerDescription;
import org.graylog2.database.MongoConnection;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;

@Singleton
public class MongoProbe {
    private static final Logger LOG = LoggerFactory.getLogger(MongoProbe.class);

    private final MongoClient mongoClient;
    private final DB db;
    private final DB adminDb;
    private final BuildInfo buildInfo;
    private final HostInfo hostInfo;

    @Inject
    public MongoProbe(MongoConnection mongoConnection) {
        this(mongoConnection.connect(), mongoConnection.getDatabase());
    }

    @VisibleForTesting
    MongoProbe(MongoClient mongoClient, DB db) {
        this(mongoClient, db, mongoClient.getDB("admin"),
                createBuildInfo(mongoClient.getDB("admin")), createHostInfo(mongoClient.getDB("admin")));
    }

    @VisibleForTesting
    MongoProbe(MongoClient mongoClient, DB db, DB adminDB, BuildInfo buildInfo, HostInfo hostInfo) {
        this.mongoClient = checkNotNull(mongoClient);
        this.db = checkNotNull(db);
        this.adminDb = checkNotNull(adminDB);
        this.buildInfo = buildInfo;
        this.hostInfo = hostInfo;
    }

    private static HostInfo createHostInfo(DB adminDb) {
        final HostInfo hostInfo;
        final CommandResult hostInfoResult = adminDb.command("hostInfo");
        if (hostInfoResult.ok()) {
            final BasicDBObject systemMap = (BasicDBObject) hostInfoResult.get("system");
            final HostInfo.System system = HostInfo.System.create(
                    new DateTime(systemMap.getDate("currentTime")),
                    systemMap.getString("hostname"),
                    systemMap.getInt("cpuAddrSize"),
                    systemMap.getLong("memSizeMB"),
                    systemMap.getInt("numCores"),
                    systemMap.getString("cpuArch"),
                    systemMap.getBoolean("numaEnabled")
            );
            final BasicDBObject osMap = (BasicDBObject) hostInfoResult.get("os");
            final HostInfo.Os os = HostInfo.Os.create(
                    osMap.getString("type"),
                    osMap.getString("name"),
                    osMap.getString("version")
            );

            final BasicDBObject extraMap = (BasicDBObject) hostInfoResult.get("extra");
            final HostInfo.Extra extra = HostInfo.Extra.create(
                    extraMap.getString("versionString"),
                    extraMap.getString("libcVersion"),
                    extraMap.getString("kernelVersion"),
                    extraMap.getString("cpuFrequencyMHz"),
                    extraMap.getString("cpuFeatures"),
                    extraMap.getString("scheduler"),
                    extraMap.getLong("pageSize", -1L),
                    extraMap.getLong("numPages", -1L),
                    extraMap.getLong("maxOpenFiles", -1L)
            );

            hostInfo = HostInfo.create(system, os, extra);
        } else {
            LOG.debug("Couldn't retrieve MongoDB hostInfo: {}", hostInfoResult.getErrorMessage());
            hostInfo = null;
        }

        return hostInfo;
    }

    private static BuildInfo createBuildInfo(DB adminDb) {
        final BuildInfo buildInfo;
        final CommandResult buildInfoResult = adminDb.command("buildInfo");
        if (buildInfoResult.ok()) {
            buildInfo = BuildInfo.create(
                    buildInfoResult.getString("version"),
                    buildInfoResult.getString("gitVersion"),
                    buildInfoResult.getString("sysInfo"),
                    buildInfoResult.getString("loaderFlags"),
                    buildInfoResult.getString("compilerFlags"),
                    buildInfoResult.getString("allocator"),
                    (List) buildInfoResult.get("versionArray"),
                    buildInfoResult.getString("javascriptEngine"),
                    buildInfoResult.getInt("bits"),
                    buildInfoResult.getBoolean("debug"),
                    buildInfoResult.getLong("maxBsonObjectSize")

            );
        } else {
            LOG.debug("Couldn't retrieve MongoDB buildInfo: {}", buildInfoResult.getErrorMessage());
            buildInfo = null;
        }

        return buildInfo;
    }

    public MongoStats mongoStats() {
        final List serverAddresses = mongoClient.getClusterDescription().getServerDescriptions()
                .stream()
                .map(ServerDescription::getAddress)
                .collect(Collectors.toList());
        final List servers = Lists.newArrayListWithCapacity(serverAddresses.size());
        for (ServerAddress serverAddress : serverAddresses) {
            servers.add(HostAndPort.fromParts(serverAddress.getHost(), serverAddress.getPort()));
        }

        final DatabaseStats dbStats;
        final CommandResult dbStatsResult = db.command("dbStats");
        if (dbStatsResult.ok()) {
            final BasicDBObject extentFreeListMap = (BasicDBObject) dbStatsResult.get("extentFreeList");
            final DatabaseStats.ExtentFreeList extentFreeList;
            if (extentFreeListMap == null) {
                extentFreeList = null;
            } else {
                extentFreeList = DatabaseStats.ExtentFreeList.create(
                        extentFreeListMap.getInt("num"),
                        extentFreeListMap.getInt("totalSize")
                );
            }

            final BasicDBObject dataFileVersionMap = (BasicDBObject) dbStatsResult.get("dataFileVersion");
            final DatabaseStats.DataFileVersion dataFileVersion;
            if (dataFileVersionMap == null) {
                dataFileVersion = null;
            } else {
                dataFileVersion = DatabaseStats.DataFileVersion.create(
                        dataFileVersionMap.getInt("major"),
                        dataFileVersionMap.getInt("minor")
                );
            }

            dbStats = DatabaseStats.create(
                    dbStatsResult.getString("db"),
                    dbStatsResult.getLong("collections"),
                    dbStatsResult.getLong("objects"),
                    dbStatsResult.getDouble("avgObjSize"),
                    dbStatsResult.getLong("dataSize"),
                    dbStatsResult.getLong("storageSize"),
                    dbStatsResult.containsField("numExtents") ? dbStatsResult.getLong("numExtents") : null,
                    dbStatsResult.getLong("indexes"),
                    dbStatsResult.getLong("indexSize"),
                    dbStatsResult.containsField("fileSize") ? dbStatsResult.getLong("fileSize") : null,
                    dbStatsResult.containsField("nsSizeMB") ? dbStatsResult.getLong("nsSizeMB") : null,
                    extentFreeList,
                    dataFileVersion
            );
        } else {
            LOG.debug("Couldn't retrieve MongoDB dbStats: {}", dbStatsResult.getErrorMessage());
            dbStats = null;
        }

        final ServerStatus serverStatus;
        final CommandResult serverStatusResult = adminDb.command("serverStatus");
        if (serverStatusResult.ok()) {
            final BasicDBObject connectionsMap = (BasicDBObject) serverStatusResult.get("connections");
            final ServerStatus.Connections connections = ServerStatus.Connections.create(
                    connectionsMap.getInt("current"),
                    connectionsMap.getInt("available"),
                    connectionsMap.containsField("totalCreated") ? connectionsMap.getLong("totalCreated") : null
            );

            final BasicDBObject networkMap = (BasicDBObject) serverStatusResult.get("network");
            final ServerStatus.Network network = ServerStatus.Network.create(
                    networkMap.getInt("bytesIn"),
                    networkMap.getInt("bytesOut"),
                    networkMap.getInt("numRequests")
            );

            final BasicDBObject memoryMap = (BasicDBObject) serverStatusResult.get("mem");
            final ServerStatus.Memory memory = ServerStatus.Memory.create(
                    memoryMap.getInt("bits"),
                    memoryMap.getInt("resident"),
                    memoryMap.getInt("virtual"),
                    memoryMap.getBoolean("supported"),
                    memoryMap.getInt("mapped", -1),
                    memoryMap.getInt("mappedWithJournal", -1)
            );

            final BasicDBObject storageEngineMap = (BasicDBObject) serverStatusResult.get("storageEngine");
            final ServerStatus.StorageEngine storageEngine;
            if (storageEngineMap == null) {
                storageEngine = ServerStatus.StorageEngine.DEFAULT;
            } else {
                storageEngine = ServerStatus.StorageEngine.create(storageEngineMap.getString("name"));
            }

            final int uptime = serverStatusResult.getInt("uptime", 0);
            serverStatus = ServerStatus.create(
                    serverStatusResult.getString("host"),
                    serverStatusResult.getString("version"),
                    serverStatusResult.getString("process"),
                    serverStatusResult.getLong("pid", 0),
                    uptime,
                    serverStatusResult.getLong("uptimeMillis", uptime * 1000L),
                    serverStatusResult.getInt("uptimeEstimate"),
                    new DateTime(serverStatusResult.getDate("localTime")),
                    connections,
                    network,
                    memory,
                    storageEngine);
        } else {
            LOG.debug("Couldn't retrieve MongoDB serverStatus: {}", serverStatusResult.getErrorMessage());
            serverStatus = null;
        }

        // TODO Collection stats? http://docs.mongodb.org/manual/reference/command/collStats/
        return MongoStats.create(servers, buildInfo, hostInfo, serverStatus, dbStats);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy