# MongoDB Comprehensive Monitoring Scripts
## Table of Contents
1. [Master Monitoring Script](#master-monitoring-script)
2. [Performance Monitoring](#performance-monitoring)
3. [Replication Monitoring](#replication-monitoring)
4. [Sharding Monitoring](#sharding-monitoring)
5. [Storage Monitoring](#storage-monitoring)
6. [Connection Monitoring](#connection-monitoring)
7. [Query Performance Monitoring](#query-performance-monitoring)
8. [Index Monitoring](#index-monitoring)
9. [OpLog Monitoring](#oplog-monitoring)
10. [Alert Script](#alert-script)
## Master Monitoring Script
```bash
#!/bin/bash
# MongoDB Master Monitoring Script
# This script provides a comprehensive view of MongoDB health
# Configuration
MONGO_HOST="${MONGO_HOST:-localhost}"
MONGO_PORT="${MONGO_PORT:-27017}"
MONGO_USER="${MONGO_USER:-}"
MONGO_PASS="${MONGO_PASS:-}"
LOG_DIR="/var/log/mongodb-monitoring"
ALERT_EMAIL="admin@example.com"
# Create log directory if it doesn't exist
mkdir -p "$LOG_DIR"
# Set MongoDB connection string
if [ -n "$MONGO_USER" ] && [ -n "$MONGO_PASS" ]; then
MONGO_CONN="mongodb://${MONGO_USER}:${MONGO_PASS}@${MONGO_HOST}:${MONGO_PORT}/admin?authSource=admin"
else
MONGO_CONN="mongodb://${MONGO_HOST}:${MONGO_PORT}/admin"
fi
# Function to run MongoDB commands
run_mongo() {
mongosh --quiet "$MONGO_CONN" --eval "$1"
}
# Main monitoring function
monitor_mongodb() {
echo "==================================================="
echo "MongoDB Monitoring Report - $(date)"
echo "==================================================="
# Server Status
echo -e "\n[SERVER STATUS]"
run_mongo "
var status = db.serverStatus();
print('Host: ' + status.host);
print('Version: ' + status.version);
print('Uptime: ' + Math.floor(status.uptime/3600) + ' hours');
print('Current Connections: ' + status.connections.current);
print('Available Connections: ' + status.connections.available);
"
# Memory Usage
echo -e "\n[MEMORY USAGE]"
run_mongo "
var status = db.serverStatus();
var mem = status.mem;
print('Resident Memory: ' + (mem.resident/1024).toFixed(2) + ' GB');
print('Virtual Memory: ' + (mem.virtual/1024).toFixed(2) + ' GB');
print('Mapped Memory: ' + ((mem.mapped || 0)/1024).toFixed(2) + ' GB');
"
# Database Stats
echo -e "\n[DATABASE STATISTICS]"
run_mongo "
db.adminCommand('listDatabases').databases.forEach(function(database) {
var dbStats = db.getSiblingDB(database.name).stats();
print('\\nDatabase: ' + database.name);
print(' Size on Disk: ' + (dbStats.dataSize/1024/1024/1024).toFixed(2) + ' GB');
print(' Storage Size: ' + (dbStats.storageSize/1024/1024/1024).toFixed(2) + ' GB');
print(' Index Size: ' + (dbStats.indexSize/1024/1024/1024).toFixed(2) + ' GB');
print(' Collections: ' + dbStats.collections);
print(' Objects: ' + dbStats.objects);
});
"
# Replication Status
echo -e "\n[REPLICATION STATUS]"
run_mongo "
var replStatus = rs.status();
if (replStatus.ok) {
print('Replica Set: ' + replStatus.set);
print('Members:');
replStatus.members.forEach(function(member) {
var lag = member.optimeDate ?
(replStatus.date - member.optimeDate)/1000 : 'N/A';
print(' ' + member.name + ' - ' + member.stateStr +
' - Lag: ' + lag + 's');
});
} else {
print('Not running with replication');
}
"
}
# Run monitoring and save to log
monitor_mongodb | tee "$LOG_DIR/mongodb_monitor_$(date +%Y%m%d_%H%M%S).log"
```
## Performance Monitoring
```bash
#!/bin/bash
# MongoDB Performance Monitoring Script
# Configuration
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
INTERVAL=5 # Monitoring interval in seconds
DURATION=60 # Total duration in seconds
echo "MongoDB Performance Monitor - Collecting metrics every ${INTERVAL}s for ${DURATION}s"
echo "========================================================================="
# Performance monitoring function
monitor_performance() {
END_TIME=$(($(date +%s) + DURATION))
while [ $(date +%s) -lt $END_TIME ]; do
echo -e "\n[$(date '+%Y-%m-%d %H:%M:%S')]"
mongosh --quiet "$MONGO_CONN" --eval "
var status = db.serverStatus();
// Operations per second
var opcounters = status.opcounters;
print('Operations/sec:');
print(' Insert: ' + opcounters.insert);
print(' Query: ' + opcounters.query);
print(' Update: ' + opcounters.update);
print(' Delete: ' + opcounters.delete);
print(' Command: ' + opcounters.command);
// Network stats
var network = status.network;
print('\\nNetwork:');
print(' Bytes In: ' + (network.bytesIn/1024/1024).toFixed(2) + ' MB');
print(' Bytes Out: ' + (network.bytesOut/1024/1024).toFixed(2) + ' MB');
print(' Num Requests: ' + network.numRequests);
// Global lock
var globalLock = status.globalLock;
print('\\nGlobal Lock:');
print(' Total Time: ' + globalLock.totalTime);
print(' Current Queue Total: ' + globalLock.currentQueue.total);
print(' Current Queue Readers: ' + globalLock.currentQueue.readers);
print(' Current Queue Writers: ' + globalLock.currentQueue.writers);
// WiredTiger cache stats
if (status.wiredTiger) {
var cache = status.wiredTiger.cache;
print('\\nWiredTiger Cache:');
print(' Bytes in cache: ' + (cache['bytes currently in the cache']/1024/1024/1024).toFixed(2) + ' GB');
print(' Max bytes configured: ' + (cache['maximum bytes configured']/1024/1024/1024).toFixed(2) + ' GB');
print(' Dirty bytes: ' + (cache['tracked dirty bytes in the cache']/1024/1024).toFixed(2) + ' MB');
}
"
sleep $INTERVAL
done
}
# Calculate operations rate
calculate_ops_rate() {
echo -e "\n[Calculating Operation Rates]"
mongosh --quiet "$MONGO_CONN" --eval "
function getOpCounters() {
return db.serverStatus().opcounters;
}
var before = getOpCounters();
sleep(5000); // 5 second interval
var after = getOpCounters();
print('Operations per second (5s average):');
print(' Insert: ' + ((after.insert - before.insert) / 5));
print(' Query: ' + ((after.query - before.query) / 5));
print(' Update: ' + ((after.update - before.update) / 5));
print(' Delete: ' + ((after.delete - before.delete) / 5));
print(' Command: ' + ((after.command - before.command) / 5));
print(' Total: ' + (
(after.insert - before.insert +
after.query - before.query +
after.update - before.update +
after.delete - before.delete +
after.command - before.command) / 5
));
"
}
# Run monitoring
monitor_performance
calculate_ops_rate
```
## Replication Monitoring
```bash
#!/bin/bash
# MongoDB Replication Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Replication Monitor"
echo "=========================="
# Check replication status
check_replication() {
mongosh --quiet "$MONGO_CONN" --eval "
try {
var status = rs.status();
var config = rs.config();
print('\\nReplica Set: ' + status.set);
print('Version: ' + config.version);
print('Protocol Version: ' + config.protocolVersion);
print('\\nMembers Status:');
print('=' .repeat(80));
// Primary info
var primary = status.members.find(m => m.state === 1);
if (primary) {
print('\\nPRIMARY: ' + primary.name);
print(' Uptime: ' + primary.uptime + ' seconds');
print(' OpTime: ' + primary.optime.ts.getTime());
}
// All members detailed info
status.members.forEach(function(member) {
print('\\nMember: ' + member.name);
print(' State: ' + member.stateStr);
print(' Health: ' + member.health);
print(' Uptime: ' + (member.uptime || 'N/A') + ' seconds');
if (member.state !== 1 && primary) { // If not primary
var lag = primary.optimeDate - member.optimeDate;
print(' Replication Lag: ' + (lag/1000) + ' seconds');
}
print(' Last Heartbeat: ' + (member.lastHeartbeat || 'N/A'));
print(' Ping MS: ' + (member.pingMs || 'N/A'));
if (member.errmsg) {
print(' ERROR: ' + member.errmsg);
}
});
// Oplog information
print('\\n' + '='.repeat(80));
print('\\nOplog Information:');
var oplog = db.getSiblingDB('local').oplog.rs.stats();
print(' Oplog Size: ' + (oplog.size/1024/1024/1024).toFixed(2) + ' GB');
print(' Used Space: ' + (oplog.storageSize/1024/1024/1024).toFixed(2) + ' GB');
print(' Count: ' + oplog.count);
// Get oplog window
var firstOp = db.getSiblingDB('local').oplog.rs.find().sort({ts: 1}).limit(1).toArray()[0];
var lastOp = db.getSiblingDB('local').oplog.rs.find().sort({ts: -1}).limit(1).toArray()[0];
if (firstOp && lastOp) {
var oplogWindow = (lastOp.ts.getTime() - firstOp.ts.getTime()) / 1000 / 3600;
print(' Oplog Window: ' + oplogWindow.toFixed(2) + ' hours');
}
} catch(e) {
print('Error checking replication: ' + e.message);
print('This server may not be part of a replica set.');
}
"
}
# Check for replication issues
check_replication_issues() {
echo -e "\n\nChecking for Replication Issues..."
echo "================================="
mongosh --quiet "$MONGO_CONN" --eval "
try {
var status = rs.status();
var issues = [];
// Check for unhealthy members
status.members.forEach(function(member) {
if (member.health !== 1) {
issues.push('UNHEALTHY: ' + member.name + ' - ' + member.stateStr);
}
// Check for high replication lag
if (member.state === 2) { // Secondary
var primary = status.members.find(m => m.state === 1);
if (primary) {
var lag = (primary.optimeDate - member.optimeDate) / 1000;
if (lag > 60) { // More than 60 seconds
issues.push('HIGH LAG: ' + member.name + ' - ' + lag + ' seconds behind');
}
}
}
// Check for recovering members
if (member.state === 3) {
issues.push('RECOVERING: ' + member.name);
}
});
// Check if there's no primary
if (!status.members.some(m => m.state === 1)) {
issues.push('CRITICAL: No primary elected!');
}
if (issues.length > 0) {
print('\\nISSUES FOUND:');
issues.forEach(function(issue) {
print(' ⚠️ ' + issue);
});
} else {
print('✅ No replication issues detected.');
}
} catch(e) {
print('Error checking for issues: ' + e.message);
}
"
}
# Monitor replication lag over time
monitor_replication_lag() {
echo -e "\n\nMonitoring Replication Lag (30 seconds)..."
echo "========================================"
for i in {1..6}; do
echo -e "\n[$(date '+%Y-%m-%d %H:%M:%S')]"
mongosh --quiet "$MONGO_CONN" --eval "
try {
var status = rs.status();
var primary = status.members.find(m => m.state === 1);
if (primary) {
print('Primary: ' + primary.name);
status.members.forEach(function(member) {
if (member.state === 2) { // Secondary
var lag = (primary.optimeDate - member.optimeDate) / 1000;
print(' ' + member.name + ' lag: ' + lag.toFixed(2) + 's');
}
});
}
} catch(e) {}
"
sleep 5
done
}
# Run all checks
check_replication
check_replication_issues
monitor_replication_lag
```
## Sharding Monitoring
```bash
#!/bin/bash
# MongoDB Sharding Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Sharding Monitor"
echo "======================="
# Check if sharding is enabled
check_sharding_status() {
mongosh --quiet "$MONGO_CONN" --eval "
try {
var configDB = db.getSiblingDB('config');
var adminDB = db.getSiblingDB('admin');
// Check if this is a sharded cluster
var shardingState = adminDB.runCommand({shardingState: 1});
if (!shardingState.enabled) {
print('Sharding is not enabled on this instance.');
return;
}
print('\\nSHARDING STATUS');
print('=' .repeat(80));
// List shards
print('\\nShards:');
configDB.shards.find().forEach(function(shard) {
print(' ' + shard._id + ': ' + shard.host);
print(' State: ' + (shard.state || 'active'));
print(' Tags: ' + (shard.tags || 'none'));
});
// Sharded databases
print('\\nSharded Databases:');
configDB.databases.find({partitioned: true}).forEach(function(db) {
print(' Database: ' + db._id);
print(' Primary Shard: ' + db.primary);
// Collections in this database
configDB.collections.find({_id: {$regex: '^' + db._id + '\\.'}}).forEach(function(coll) {
print('\\n Collection: ' + coll._id);
print(' Shard Key: ' + JSON.stringify(coll.key));
print(' Unique: ' + coll.unique);
// Chunk distribution
var chunkCounts = {};
configDB.chunks.find({ns: coll._id}).forEach(function(chunk) {
chunkCounts[chunk.shard] = (chunkCounts[chunk.shard] || 0) + 1;
});
print(' Chunk Distribution:');
Object.keys(chunkCounts).forEach(function(shard) {
print(' ' + shard + ': ' + chunkCounts[shard] + ' chunks');
});
});
});
// Balancer status
print('\\n' + '='.repeat(80));
print('\\nBalancer Status:');
var balancerStatus = configDB.settings.findOne({_id: 'balancer'});
print(' Mode: ' + (balancerStatus ? balancerStatus.mode : 'full'));
print(' Stopped: ' + (balancerStatus && balancerStatus.stopped ? 'Yes' : 'No'));
// Active migrations
print('\\nActive Migrations:');
var migrations = configDB.migrations.find({}).toArray();
if (migrations.length > 0) {
migrations.forEach(function(migration) {
print(' ' + migration.ns + ': ' + migration.from + ' -> ' + migration.to);
});
} else {
print(' None');
}
} catch(e) {
print('Error checking sharding status: ' + e.message);
}
"
}
# Monitor chunk operations
monitor_chunk_operations() {
echo -e "\n\nMonitoring Chunk Operations..."
echo "============================="
mongosh --quiet "$MONGO_CONN" --eval "
var configDB = db.getSiblingDB('config');
// Recent chunk splits
print('\\nRecent Chunk Splits (last 24 hours):');
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
configDB.changelog.find({
what: 'split',
time: {$gte: yesterday}
}).sort({time: -1}).limit(5).forEach(function(entry) {
print(' ' + entry.time.toISOString() + ' - ' + entry.ns + ' on ' + entry.shard);
});
// Recent migrations
print('\\nRecent Chunk Migrations (last 24 hours):');
configDB.changelog.find({
what: 'moveChunk.from',
time: {$gte: yesterday}
}).sort({time: -1}).limit(5).forEach(function(entry) {
print(' ' + entry.time.toISOString() + ' - ' + entry.ns);
print(' ' + entry.details.from + ' -> ' + entry.details.to);
print(' Status: ' + entry.details.status);
});
// Check for jumbo chunks
print('\\nJumbo Chunks:');
var jumboCount = 0;
configDB.chunks.find({jumbo: true}).forEach(function(chunk) {
print(' ' + chunk.ns + ' - Shard: ' + chunk.shard);
print(' Min: ' + JSON.stringify(chunk.min));
print(' Max: ' + JSON.stringify(chunk.max));
jumboCount++;
});
if (jumboCount === 0) {
print(' No jumbo chunks found');
}
"
}
# Check shard key effectiveness
check_shard_key_effectiveness() {
echo -e "\n\nShard Key Effectiveness Analysis..."
echo "================================="
mongosh --quiet "$MONGO_CONN" --eval "
var configDB = db.getSiblingDB('config');
print('\\nShard Key Analysis:');
configDB.collections.find().forEach(function(coll) {
var totalChunks = configDB.chunks.count({ns: coll._id});
if (totalChunks === 0) return;
print('\\nCollection: ' + coll._id);
print(' Shard Key: ' + JSON.stringify(coll.key));
print(' Total Chunks: ' + totalChunks);
// Check chunk distribution
var shardCounts = {};
var maxChunkSize = 0;
var minChunkSize = Number.MAX_VALUE;
configDB.chunks.find({ns: coll._id}).forEach(function(chunk) {
shardCounts[chunk.shard] = (shardCounts[chunk.shard] || 0) + 1;
});
Object.values(shardCounts).forEach(function(count) {
maxChunkSize = Math.max(maxChunkSize, count);
minChunkSize = Math.min(minChunkSize, count);
});
var imbalance = maxChunkSize - minChunkSize;
var imbalanceRatio = (imbalance / totalChunks * 100).toFixed(2);
print(' Chunk Distribution Imbalance: ' + imbalance + ' chunks (' + imbalanceRatio + '%)');
if (imbalanceRatio > 20) {
print(' ⚠️ WARNING: High imbalance detected!');
}
});
"
}
# Run all sharding checks
check_sharding_status
monitor_chunk_operations
check_shard_key_effectiveness
```
## Storage Monitoring
```bash
#!/bin/bash
# MongoDB Storage Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Storage Monitor"
echo "======================"
# Check storage statistics
check_storage_stats() {
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nSTORAGE STATISTICS');
print('=' .repeat(80));
// Get all databases
db.adminCommand('listDatabases').databases.forEach(function(database) {
var currentDb = db.getSiblingDB(database.name);
var stats = currentDb.stats();
print('\\nDatabase: ' + database.name);
print(' Data Size: ' + (stats.dataSize / 1024 / 1024 / 1024).toFixed(3) + ' GB');
print(' Storage Size: ' + (stats.storageSize / 1024 / 1024 / 1024).toFixed(3) + ' GB');
print(' Index Size: ' + (stats.indexSize / 1024 / 1024 / 1024).toFixed(3) + ' GB');
print(' Total Size: ' + ((stats.dataSize + stats.indexSize) / 1024 / 1024 / 1024).toFixed(3) + ' GB');
print(' Storage Efficiency: ' + ((stats.dataSize / stats.storageSize * 100).toFixed(2)) + '%');
print(' Average Object Size: ' + (stats.avgObjSize || 0).toFixed(0) + ' bytes');
print(' Collections: ' + stats.collections);
print(' Objects: ' + stats.objects.toLocaleString());
// Collection details
if (database.name !== 'local' && database.name !== 'admin') {
print('\\n Top Collections by Size:');
currentDb.getCollectionNames().forEach(function(collName) {
var collStats = currentDb.getCollection(collName).stats();
var totalSize = (collStats.size + collStats.totalIndexSize) / 1024 / 1024;
if (totalSize > 10) { // Only show collections > 10MB
print(' ' + collName + ': ' + totalSize.toFixed(2) + ' MB');
}
});
}
});
"
}
# Monitor disk usage
monitor_disk_usage() {
echo -e "\n\nDisk Usage Analysis..."
echo "===================="
mongosh --quiet "$MONGO_CONN" --eval "
var adminDb = db.getSiblingDB('admin');
var serverStatus = adminDb.serverStatus();
// Get dbPath from server status
var dbPath = adminDb.runCommand({getCmdLineOpts: 1}).parsed.storage.dbPath;
print('\\nDatabase Path: ' + dbPath);
// WiredTiger specific stats
if (serverStatus.storageEngine.name === 'wiredTiger') {
var wtStats = serverStatus.wiredTiger;
print('\\nWiredTiger Cache Statistics:');
var cache = wtStats.cache;
print(' Maximum bytes configured: ' + (cache['maximum bytes configured'] / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Currently in cache: ' + (cache['bytes currently in the cache'] / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Dirty bytes in cache: ' + (cache['tracked dirty bytes in the cache'] / 1024 / 1024).toFixed(2) + ' MB');
print(' Cache used %: ' + ((cache['bytes currently in the cache'] / cache['maximum bytes configured'] * 100).toFixed(2)) + '%');
print('\\nWiredTiger Block Manager:');
var blockManager = wtStats['block-manager'];
print(' Blocks read: ' + blockManager['blocks read'].toLocaleString());
print(' Blocks written: ' + blockManager['blocks written'].toLocaleString());
print(' Bytes read: ' + (blockManager['bytes read'] / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Bytes written: ' + (blockManager['bytes written'] / 1024 / 1024 / 1024).toFixed(2) + ' GB');
}
"
}
# Check for storage warnings
check_storage_warnings() {
echo -e "\n\nStorage Health Check..."
echo "===================="
mongosh --quiet "$MONGO_CONN" --eval "
var warnings = [];
// Check each database
db.adminCommand('listDatabases').databases.forEach(function(database) {
var stats = db.getSiblingDB(database.name).stats();
// Check storage efficiency
var efficiency = stats.dataSize / stats.storageSize * 100;
if (efficiency < 50) {
warnings.push('Low storage efficiency in ' + database.name + ': ' + efficiency.toFixed(2) + '%');
}
// Check for large databases
var totalSizeGB = (stats.dataSize + stats.indexSize) / 1024 / 1024 / 1024;
if (totalSizeGB > 100) {
warnings.push('Large database detected: ' + database.name + ' (' + totalSizeGB.toFixed(2) + ' GB)');
}
// Check index to data ratio
var indexRatio = stats.indexSize / stats.dataSize * 100;
if (indexRatio > 100) {
warnings.push('High index ratio in ' + database.name + ': ' + indexRatio.toFixed(2) + '%');
}
});
// Check WiredTiger cache pressure
var serverStatus = db.serverStatus();
if (serverStatus.storageEngine.name === 'wiredTiger') {
var cache = serverStatus.wiredTiger.cache;
var cacheUsedPct = cache['bytes currently in the cache'] / cache['maximum bytes configured'] * 100;
if (cacheUsedPct > 95) {
warnings.push('High WiredTiger cache usage: ' + cacheUsedPct.toFixed(2) + '%');
}
var dirtyPct = cache['tracked dirty bytes in the cache'] / cache['maximum bytes configured'] * 100;
if (dirtyPct > 20) {
warnings.push('High dirty cache percentage: ' + dirtyPct.toFixed(2) + '%');
}
}
if (warnings.length > 0) {
print('\\n⚠️ WARNINGS DETECTED:');
warnings.forEach(function(warning) {
print(' - ' + warning);
});
} else {
print('\\n✅ No storage warnings detected.');
}
"
}
# Run all storage checks
check_storage_stats
monitor_disk_usage
check_storage_warnings
```
## Connection Monitoring
```bash
#!/bin/bash
# MongoDB Connection Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Connection Monitor"
echo "========================="
# Monitor current connections
monitor_connections() {
mongosh --quiet "$MONGO_CONN" --eval "
var serverStatus = db.serverStatus();
var connections = serverStatus.connections;
print('\\nCONNECTION OVERVIEW');
print('=' .repeat(80));
print('Current Connections: ' + connections.current);
print('Available Connections: ' + connections.available);
print('Total Created: ' + connections.totalCreated);
print('Connection Usage: ' + (connections.current / (connections.current + connections.available) * 100).toFixed(2) + '%');
// Network statistics
var network = serverStatus.network;
print('\\nNETWORK STATISTICS');
print('Bytes In: ' + (network.bytesIn / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print('Bytes Out: ' + (network.bytesOut / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print('Num Requests: ' + network.numRequests.toLocaleString());
// Get current operations grouped by client
print('\\nACTIVE CONNECTIONS BY CLIENT');
print('-' .repeat(80));
var clientOps = {};
db.currentOp(true).inprog.forEach(function(op) {
if (op.client) {
var client = op.client.split(':')[0];
if (!clientOps[client]) {
clientOps[client] = {
count: 0,
operations: []
};
}
clientOps[client].count++;
if (op.op && op.op !== 'none') {
clientOps[client].operations.push(op.op);
}
}
});
Object.keys(clientOps).sort().forEach(function(client) {
var info = clientOps[client];
print('\\nClient: ' + client);
print(' Active Operations: ' + info.count);
if (info.operations.length > 0) {
var opCounts = {};
info.operations.forEach(function(op) {
opCounts[op] = (opCounts[op] || 0) + 1;
});
print(' Operation Types: ' + JSON.stringify(opCounts));
}
});
// Connection pool stats
print('\\n' + '=' .repeat(80));
print('\\nCONNECTION DETAILS');
// Get all current connections
var currentOps = db.currentOp(true).inprog;
var connectionTypes = {};
var longRunning = [];
currentOps.forEach(function(op) {
// Categorize connections
var type = op.desc || 'unknown';
if (type.includes('conn')) type = 'client';
else if (type.includes('repl')) type = 'replication';
else if (type.includes('TTLMonitor')) type = 'ttl';
connectionTypes[type] = (connectionTypes[type] || 0) + 1;
// Check for long-running operations
if (op.active && op.secs_running > 60) {
longRunning.push({
opid: op.opid,
ns: op.ns || 'N/A',
op: op.op || 'N/A',
running: op.secs_running,
client: op.client || 'N/A'
});
}
});
print('\\nConnection Types:');
Object.keys(connectionTypes).forEach(function(type) {
print(' ' + type + ': ' + connectionTypes[type]);
});
if (longRunning.length > 0) {
print('\\nLONG-RUNNING OPERATIONS (>60s):');
longRunning.forEach(function(op) {
print(' OpID: ' + op.opid);
print(' Namespace: ' + op.ns);
print(' Operation: ' + op.op);
print(' Running Time: ' + op.running + ' seconds');
print(' Client: ' + op.client);
});
}
"
}
# Monitor connection changes over time
monitor_connection_changes() {
echo -e "\n\nMonitoring Connection Changes (30 seconds)..."
echo "==========================================="
for i in {1..6}; do
echo -e "\n[$(date '+%Y-%m-%d %H:%M:%S')]"
mongosh --quiet "$MONGO_CONN" --eval "
var conns = db.serverStatus().connections;
print('Connections: ' + conns.current + '/' + (conns.current + conns.available));
// Show top operations
var ops = db.currentOp().inprog.filter(function(op) {
return op.active && op.op !== 'none';
});
if (ops.length > 0) {
print('Active Ops: ' + ops.length);
ops.slice(0, 3).forEach(function(op) {
print(' - ' + op.op + ' on ' + (op.ns || 'N/A') +
' (' + (op.secs_running || 0) + 's)');
});
}
"
sleep 5
done
}
# Run connection monitoring
monitor_connections
monitor_connection_changes
```
## Query Performance Monitoring
```bash
#!/bin/bash
# MongoDB Query Performance Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Query Performance Monitor"
echo "================================"
# Analyze slow queries
analyze_slow_queries() {
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nSLOW QUERY ANALYSIS');
print('=' .repeat(80));
// Get profiling level for each database
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
var profilingLevel = currentDb.getProfilingStatus();
print('\\nDatabase: ' + database.name);
print(' Profiling Level: ' + profilingLevel.was);
print(' Slow MS Threshold: ' + profilingLevel.slowms);
if (profilingLevel.was > 0) {
// Get slow queries from system.profile
var slowQueries = currentDb.system.profile.find({
millis: {$gt: profilingLevel.slowms}
}).sort({ts: -1}).limit(10).toArray();
if (slowQueries.length > 0) {
print('\\n Recent Slow Queries:');
slowQueries.forEach(function(query) {
print('\\n Timestamp: ' + query.ts);
print(' Operation: ' + query.op);
print(' Namespace: ' + query.ns);
print(' Duration: ' + query.millis + 'ms');
print(' Examined: ' + (query.docsExamined || 0) + ' docs');
print(' Returned: ' + (query.nreturned || 0) + ' docs');
print(' Index Used: ' + (query.planSummary || 'UNKNOWN'));
if (query.command) {
print(' Command: ' + JSON.stringify(query.command).substring(0, 100) + '...');
}
});
} else {
print('\\n No slow queries found in profile collection');
}
} else {
print('\\n ⚠️ Profiling is disabled for this database');
}
});
"
}
# Check current operations
check_current_operations() {
echo -e "\n\nCurrent Operations Analysis..."
echo "============================="
mongosh --quiet "$MONGO_CONN" --eval "
var currentOps = db.currentOp().inprog;
print('Total Operations: ' + currentOps.length);
// Filter and categorize operations
var activeOps = currentOps.filter(function(op) {
return op.active && op.op !== 'none';
});
print('Active Operations: ' + activeOps.length);
if (activeOps.length > 0) {
print('\\nACTIVE OPERATIONS:');
print('-' .repeat(80));
activeOps.sort(function(a, b) {
return (b.secs_running || 0) - (a.secs_running || 0);
}).slice(0, 10).forEach(function(op) {
print('\\nOperation ID: ' + op.opid);
print(' Type: ' + op.op);
print(' Namespace: ' + (op.ns || 'N/A'));
print(' Running Time: ' + (op.secs_running || 0) + ' seconds');
print(' Client: ' + (op.client || 'N/A'));
if (op.command) {
var cmdStr = JSON.stringify(op.command);
print(' Command: ' + cmdStr.substring(0, 200) + (cmdStr.length > 200 ? '...' : ''));
}
if (op.planSummary) {
print(' Plan: ' + op.planSummary);
}
if (op.progress) {
print(' Progress: ' + JSON.stringify(op.progress));
}
// Highlight potential issues
if (op.secs_running > 300) {
print(' ⚠️ WARNING: Long running operation!');
}
if (op.waitingForLock) {
print(' ⚠️ WARNING: Waiting for lock!');
}
});
} else {
print('\\n✅ No active operations found');
}
// Check for lock waits
var waitingOps = currentOps.filter(function(op) {
return op.waitingForLock;
});
if (waitingOps.length > 0) {
print('\\n⚠️ OPERATIONS WAITING FOR LOCKS: ' + waitingOps.length);
waitingOps.slice(0, 5).forEach(function(op) {
print(' - ' + op.op + ' on ' + (op.ns || 'N/A'));
});
}
"
}
# Query patterns analysis
analyze_query_patterns() {
echo -e "\n\nQuery Pattern Analysis..."
echo "========================"
mongosh --quiet "$MONGO_CONN" --eval "
// This requires profiling to be enabled
print('\\nANALYZING QUERY PATTERNS');
print('(Requires profiling level 1 or 2)');
print('-' .repeat(80));
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
var profilingLevel = currentDb.getProfilingStatus();
if (profilingLevel.was > 0) {
print('\\nDatabase: ' + database.name);
// Aggregate query patterns
var patterns = currentDb.system.profile.aggregate([
{$match: {op: {$in: ['query', 'find', 'aggregate', 'count', 'distinct']}}},
{$group: {
_id: {
ns: '$ns',
op: '$op',
planSummary: '$planSummary'
},
count: {$sum: 1},
avgMillis: {$avg: '$millis'},
maxMillis: {$max: '$millis'},
avgDocsExamined: {$avg: '$docsExamined'},
avgDocsReturned: {$avg: '$nreturned'}
}},
{$sort: {count: -1}},
{$limit: 10}
]).toArray();
if (patterns.length > 0) {
print('\\n Top Query Patterns:');
patterns.forEach(function(pattern, idx) {
print('\\n ' + (idx + 1) + '. Namespace: ' + pattern._id.ns);
print(' Operation: ' + pattern._id.op);
print(' Plan: ' + (pattern._id.planSummary || 'N/A'));
print(' Count: ' + pattern.count);
print(' Avg Duration: ' + pattern.avgMillis.toFixed(2) + 'ms');
print(' Max Duration: ' + pattern.maxMillis + 'ms');
print(' Avg Docs Examined: ' + pattern.avgDocsExamined.toFixed(0));
print(' Avg Docs Returned: ' + pattern.avgDocsReturned.toFixed(0));
// Calculate efficiency
if (pattern.avgDocsExamined > 0) {
var efficiency = (pattern.avgDocsReturned / pattern.avgDocsExamined * 100);
print(' Efficiency: ' + efficiency.toFixed(2) + '%');
if (efficiency < 50) {
print(' ⚠️ Low efficiency - consider adding an index');
}
}
});
}
}
});
"
}
# Run all query performance checks
analyze_slow_queries
check_current_operations
analyze_query_patterns
```
## Index Monitoring
```bash
#!/bin/bash
# MongoDB Index Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Index Monitor"
echo "===================="
# Analyze index usage and effectiveness
analyze_indexes() {
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nINDEX ANALYSIS');
print('=' .repeat(80));
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
print('\\nDatabase: ' + database.name);
currentDb.getCollectionNames().forEach(function(collName) {
var coll = currentDb.getCollection(collName);
var indexes = coll.getIndexes();
if (indexes.length > 1) { // More than just _id index
print('\\n Collection: ' + collName);
print(' Total Indexes: ' + indexes.length);
var totalIndexSize = 0;
var stats = coll.stats();
indexes.forEach(function(index) {
print('\\n Index: ' + index.name);
print(' Keys: ' + JSON.stringify(index.key));
if (index.unique) print(' Unique: true');
if (index.sparse) print(' Sparse: true');
if (index.partialFilterExpression) {
print(' Partial: ' + JSON.stringify(index.partialFilterExpression));
}
// Get index stats if available
try {
var indexStats = coll.aggregate([
{$indexStats: {}},
{$match: {name: index.name}}
]).toArray()[0];
if (indexStats) {
print(' Usage Count: ' + indexStats.accesses.ops);
print(' Last Used: ' + (indexStats.accesses.since || 'Never'));
// Calculate days since last use
if (indexStats.accesses.since) {
var daysSinceUse = (new Date() - indexStats.accesses.since) / (1000 * 60 * 60 * 24);
if (daysSinceUse > 30) {
print(' ⚠️ WARNING: Not used in ' + daysSinceUse.toFixed(0) + ' days');
}
}
if (indexStats.accesses.ops === 0) {
print(' ⚠️ WARNING: Unused index');
}
}
} catch(e) {
// Index stats not available
}
});
// Check for redundant indexes
print('\\n Checking for redundant indexes...');
for (var i = 0; i < indexes.length; i++) {
for (var j = i + 1; j < indexes.length; j++) {
var keys1 = Object.keys(indexes[i].key);
var keys2 = Object.keys(indexes[j].key);
// Check if one index is a prefix of another
var isPrefix = true;
if (keys1.length <= keys2.length) {
for (var k = 0; k < keys1.length; k++) {
if (keys1[k] !== keys2[k]) {
isPrefix = false;
break;
}
}
if (isPrefix) {
print(' ⚠️ Potential redundancy: ' + indexes[i].name + ' is a prefix of ' + indexes[j].name);
}
}
}
}
}
});
});
"
}
# Find missing indexes based on query patterns
find_missing_indexes() {
echo -e "\n\nMissing Index Analysis..."
echo "========================"
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nCHECKING FOR MISSING INDEXES');
print('(Based on slow queries without index usage)');
print('-' .repeat(80));
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
var profilingLevel = currentDb.getProfilingStatus();
if (profilingLevel.was > 0) {
// Find queries that did collection scans
var collScans = currentDb.system.profile.find({
planSummary: 'COLLSCAN',
millis: {$gt: 100} // Only queries taking more than 100ms
}).sort({millis: -1}).limit(10).toArray();
if (collScans.length > 0) {
print('\\nDatabase: ' + database.name);
print('\\nQueries performing collection scans:');
var suggestions = {};
collScans.forEach(function(query) {
print('\\n Namespace: ' + query.ns);
print(' Duration: ' + query.millis + 'ms');
print(' Documents Examined: ' + (query.docsExamined || 'N/A'));
// Extract filter fields for index suggestions
if (query.command && query.command.filter) {
var filterKeys = Object.keys(query.command.filter);
var indexSuggestion = {};
filterKeys.forEach(function(key) {
if (!key.startsWith('$')) {
indexSuggestion[key] = 1;
}
});
if (Object.keys(indexSuggestion).length > 0) {
var suggestionKey = query.ns + ':' + JSON.stringify(indexSuggestion);
suggestions[suggestionKey] = (suggestions[suggestionKey] || 0) + 1;
}
}
});
if (Object.keys(suggestions).length > 0) {
print('\\n📌 INDEX SUGGESTIONS:');
Object.keys(suggestions).forEach(function(suggestion) {
var parts = suggestion.split(':');
print(' Collection: ' + parts[0]);
print(' Suggested Index: ' + parts[1]);
print(' Would help ' + suggestions[suggestion] + ' slow queries\\n');
});
}
}
}
});
"
}
# Index size analysis
analyze_index_sizes() {
echo -e "\n\nIndex Size Analysis..."
echo "===================="
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nINDEX SIZE BREAKDOWN');
print('-' .repeat(80));
var totalIndexSize = 0;
var largeIndexes = [];
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
var dbIndexSize = 0;
currentDb.getCollectionNames().forEach(function(collName) {
var stats = currentDb.getCollection(collName).stats();
if (stats.indexSizes) {
Object.keys(stats.indexSizes).forEach(function(indexName) {
var indexSizeMB = stats.indexSizes[indexName] / 1024 / 1024;
dbIndexSize += indexSizeMB;
if (indexSizeMB > 100) { // Indexes larger than 100MB
largeIndexes.push({
db: database.name,
collection: collName,
index: indexName,
size: indexSizeMB
});
}
});
}
});
if (dbIndexSize > 0) {
print('\\n' + database.name + ': ' + dbIndexSize.toFixed(2) + ' MB');
totalIndexSize += dbIndexSize;
}
});
print('\\nTotal Index Size: ' + totalIndexSize.toFixed(2) + ' MB');
if (largeIndexes.length > 0) {
print('\\nLarge Indexes (>100MB):');
largeIndexes.sort(function(a, b) { return b.size - a.size; }).forEach(function(idx) {
print(' ' + idx.db + '.' + idx.collection + '.' + idx.index + ': ' + idx.size.toFixed(2) + ' MB');
});
}
"
}
# Run all index checks
analyze_indexes
find_missing_indexes
analyze_index_sizes
```
## OpLog Monitoring
```bash
#!/bin/bash
# MongoDB OpLog Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB OpLog Monitor"
echo "===================="
# Monitor oplog status and size
monitor_oplog() {
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nOPLOG STATUS');
print('=' .repeat(80));
try {
var localDb = db.getSiblingDB('local');
var oplog = localDb.oplog.rs;
// Check if oplog exists (replica set member)
if (!oplog.exists()) {
print('This instance is not running as a replica set member.');
return;
}
// Oplog stats
var stats = oplog.stats();
print('\\nOplog Collection Stats:');
print(' Size: ' + (stats.size / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Storage Size: ' + (stats.storageSize / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Count: ' + stats.count.toLocaleString() + ' operations');
print(' Average Object Size: ' + stats.avgObjSize + ' bytes');
// Get first and last oplog entries
var firstOp = oplog.find().sort({ts: 1}).limit(1).toArray()[0];
var lastOp = oplog.find().sort({ts: -1}).limit(1).toArray()[0];
if (firstOp && lastOp) {
print('\\nOplog Time Range:');
print(' First Operation: ' + firstOp.ts.toString());
print(' Last Operation: ' + lastOp.ts.toString());
// Calculate oplog window
var timeDiff = lastOp.ts.getTime() - firstOp.ts.getTime();
var hours = timeDiff / 1000 / 3600;
print(' Oplog Window: ' + hours.toFixed(2) + ' hours');
if (hours < 24) {
print(' ⚠️ WARNING: Oplog window is less than 24 hours!');
}
// Calculate oplog growth rate
var recentOps = oplog.find({
ts: {$gte: new Timestamp(lastOp.ts.getTime() - 3600, 0)}
}).count();
print('\\nOplog Growth Rate:');
print(' Operations in last hour: ' + recentOps.toLocaleString());
print(' Estimated daily operations: ' + (recentOps * 24).toLocaleString());
// Estimate how long current oplog will last
var opsPerHour = recentOps;
var totalCapacity = stats.maxSize / stats.avgObjSize;
var hoursRemaining = (totalCapacity - stats.count) / opsPerHour;
print('\\nOplog Capacity:');
print(' Max Size: ' + (stats.maxSize / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Current Usage: ' + ((stats.size / stats.maxSize) * 100).toFixed(2) + '%');
print(' Estimated Hours Until Full: ' + hoursRemaining.toFixed(2));
if (hoursRemaining < 48) {
print(' ⚠️ WARNING: Oplog may fill up in less than 48 hours!');
}
}
// Analyze oplog operations
print('\\nOplog Operation Analysis (last 1000 operations):');
var opTypes = {};
var nsByOp = {};
oplog.find().sort({ts: -1}).limit(1000).forEach(function(op) {
opTypes[op.op] = (opTypes[op.op] || 0) + 1;
if (op.ns) {
if (!nsByOp[op.ns]) nsByOp[op.ns] = {};
nsByOp[op.ns][op.op] = (nsByOp[op.ns][op.op] || 0) + 1;
}
});
print('\\nOperation Types:');
Object.keys(opTypes).forEach(function(opType) {
var opName = {
'i': 'insert',
'u': 'update',
'd': 'delete',
'c': 'command',
'n': 'noop'
}[opType] || opType;
print(' ' + opName + ': ' + opTypes[opType] + ' (' +
(opTypes[opType] / 10).toFixed(2) + '%)');
});
// Top namespaces by operation count
print('\\nTop Namespaces by Activity:');
var nsArray = [];
Object.keys(nsByOp).forEach(function(ns) {
var total = 0;
Object.values(nsByOp[ns]).forEach(function(count) {
total += count;
});
nsArray.push({ns: ns, count: total, ops: nsByOp[ns]});
});
nsArray.sort(function(a, b) { return b.count - a.count; })
.slice(0, 5)
.forEach(function(item) {
print(' ' + item.ns + ': ' + item.count + ' operations');
});
} catch(e) {
print('Error analyzing oplog: ' + e.message);
}
"
}
# Monitor replication lag based on oplog
monitor_replication_via_oplog() {
echo -e "\n\nReplication Lag Analysis via OpLog..."
echo "===================================="
mongosh --quiet "$MONGO_CONN" --eval "
try {
var replStatus = rs.status();
if (!replStatus.ok) {
print('Not running in replica set mode');
return;
}
print('\\nMember OpLog Status:');
print('-' .repeat(80));
var primary = replStatus.members.find(m => m.state === 1);
replStatus.members.forEach(function(member) {
print('\\nMember: ' + member.name);
print(' State: ' + member.stateStr);
if (member.optime) {
print(' OpTime: ' + member.optime.ts.toString());
print(' OpTime Date: ' + member.optimeDate);
if (primary && member._id !== primary._id) {
var lagSeconds = (primary.optimeDate - member.optimeDate) / 1000;
print(' Replication Lag: ' + lagSeconds + ' seconds');
if (lagSeconds > 60) {
print(' ⚠️ WARNING: High replication lag detected!');
}
}
}
if (member.lastHeartbeat) {
var heartbeatLag = (new Date() - member.lastHeartbeat) / 1000;
if (heartbeatLag > 10) {
print(' ⚠️ WARNING: Last heartbeat was ' + heartbeatLag.toFixed(0) + ' seconds ago');
}
}
});
} catch(e) {
print('Error: ' + e.message);
}
"
}
# Run oplog monitoring
monitor_oplog
monitor_replication_via_oplog
```
## Alert Script
```bash
#!/bin/bash
# MongoDB Alert Monitoring Script
# This script checks for various issues and can send alerts
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
ALERT_EMAIL="${ALERT_EMAIL:-admin@example.com}"
ALERT_THRESHOLD_CPU=80
ALERT_THRESHOLD_MEM=90
ALERT_THRESHOLD_CONNECTIONS=80
ALERT_THRESHOLD_REPL_LAG=300 # 5 minutes
echo "MongoDB Alert Monitor"
echo "===================="
# Function to send alert (customize based on your alerting system)
send_alert() {
local severity=$1
local message=$2
echo "[${severity}] ${message}"
# Example: Send email alert
# echo "${message}" | mail -s "MongoDB Alert: ${severity}" "${ALERT_EMAIL}"
# Example: Send to monitoring system
# curl -X POST "http://monitoring-system/alert" \
# -d "{\"severity\":\"${severity}\",\"message\":\"${message}\"}"
}
# Comprehensive alert checking# MongoDB Comprehensive Monitoring Scripts
## Table of Contents
1. [Master Monitoring Script](#master-monitoring-script)
2. [Performance Monitoring](#performance-monitoring)
3. [Replication Monitoring](#replication-monitoring)
4. [Sharding Monitoring](#sharding-monitoring)
5. [Storage Monitoring](#storage-monitoring)
6. [Connection Monitoring](#connection-monitoring)
7. [Query Performance Monitoring](#query-performance-monitoring)
8. [Index Monitoring](#index-monitoring)
9. [OpLog Monitoring](#oplog-monitoring)
10. [Alert Script](#alert-script)
## Master Monitoring Script
```bash
#!/bin/bash
# MongoDB Master Monitoring Script
# This script provides a comprehensive view of MongoDB health
# Configuration
MONGO_HOST="${MONGO_HOST:-localhost}"
MONGO_PORT="${MONGO_PORT:-27017}"
MONGO_USER="${MONGO_USER:-}"
MONGO_PASS="${MONGO_PASS:-}"
LOG_DIR="/var/log/mongodb-monitoring"
ALERT_EMAIL="admin@example.com"
# Create log directory if it doesn't exist
mkdir -p "$LOG_DIR"
# Set MongoDB connection string
if [ -n "$MONGO_USER" ] && [ -n "$MONGO_PASS" ]; then
MONGO_CONN="mongodb://${MONGO_USER}:${MONGO_PASS}@${MONGO_HOST}:${MONGO_PORT}/admin?authSource=admin"
else
MONGO_CONN="mongodb://${MONGO_HOST}:${MONGO_PORT}/admin"
fi
# Function to run MongoDB commands
run_mongo() {
mongosh --quiet "$MONGO_CONN" --eval "$1"
}
# Main monitoring function
monitor_mongodb() {
echo "==================================================="
echo "MongoDB Monitoring Report - $(date)"
echo "==================================================="
# Server Status
echo -e "\n[SERVER STATUS]"
run_mongo "
var status = db.serverStatus();
print('Host: ' + status.host);
print('Version: ' + status.version);
print('Uptime: ' + Math.floor(status.uptime/3600) + ' hours');
print('Current Connections: ' + status.connections.current);
print('Available Connections: ' + status.connections.available);
"
# Memory Usage
echo -e "\n[MEMORY USAGE]"
run_mongo "
var status = db.serverStatus();
var mem = status.mem;
print('Resident Memory: ' + (mem.resident/1024).toFixed(2) + ' GB');
print('Virtual Memory: ' + (mem.virtual/1024).toFixed(2) + ' GB');
print('Mapped Memory: ' + ((mem.mapped || 0)/1024).toFixed(2) + ' GB');
"
# Database Stats
echo -e "\n[DATABASE STATISTICS]"
run_mongo "
db.adminCommand('listDatabases').databases.forEach(function(database) {
var dbStats = db.getSiblingDB(database.name).stats();
print('\\nDatabase: ' + database.name);
print(' Size on Disk: ' + (dbStats.dataSize/1024/1024/1024).toFixed(2) + ' GB');
print(' Storage Size: ' + (dbStats.storageSize/1024/1024/1024).toFixed(2) + ' GB');
print(' Index Size: ' + (dbStats.indexSize/1024/1024/1024).toFixed(2) + ' GB');
print(' Collections: ' + dbStats.collections);
print(' Objects: ' + dbStats.objects);
});
"
# Replication Status
echo -e "\n[REPLICATION STATUS]"
run_mongo "
var replStatus = rs.status();
if (replStatus.ok) {
print('Replica Set: ' + replStatus.set);
print('Members:');
replStatus.members.forEach(function(member) {
var lag = member.optimeDate ?
(replStatus.date - member.optimeDate)/1000 : 'N/A';
print(' ' + member.name + ' - ' + member.stateStr +
' - Lag: ' + lag + 's');
});
} else {
print('Not running with replication');
}
"
}
# Run monitoring and save to log
monitor_mongodb | tee "$LOG_DIR/mongodb_monitor_$(date +%Y%m%d_%H%M%S).log"
```
## Performance Monitoring
```bash
#!/bin/bash
# MongoDB Performance Monitoring Script
# Configuration
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
INTERVAL=5 # Monitoring interval in seconds
DURATION=60 # Total duration in seconds
echo "MongoDB Performance Monitor - Collecting metrics every ${INTERVAL}s for ${DURATION}s"
echo "========================================================================="
# Performance monitoring function
monitor_performance() {
END_TIME=$(($(date +%s) + DURATION))
while [ $(date +%s) -lt $END_TIME ]; do
echo -e "\n[$(date '+%Y-%m-%d %H:%M:%S')]"
mongosh --quiet "$MONGO_CONN" --eval "
var status = db.serverStatus();
// Operations per second
var opcounters = status.opcounters;
print('Operations/sec:');
print(' Insert: ' + opcounters.insert);
print(' Query: ' + opcounters.query);
print(' Update: ' + opcounters.update);
print(' Delete: ' + opcounters.delete);
print(' Command: ' + opcounters.command);
// Network stats
var network = status.network;
print('\\nNetwork:');
print(' Bytes In: ' + (network.bytesIn/1024/1024).toFixed(2) + ' MB');
print(' Bytes Out: ' + (network.bytesOut/1024/1024).toFixed(2) + ' MB');
print(' Num Requests: ' + network.numRequests);
// Global lock
var globalLock = status.globalLock;
print('\\nGlobal Lock:');
print(' Total Time: ' + globalLock.totalTime);
print(' Current Queue Total: ' + globalLock.currentQueue.total);
print(' Current Queue Readers: ' + globalLock.currentQueue.readers);
print(' Current Queue Writers: ' + globalLock.currentQueue.writers);
// WiredTiger cache stats
if (status.wiredTiger) {
var cache = status.wiredTiger.cache;
print('\\nWiredTiger Cache:');
print(' Bytes in cache: ' + (cache['bytes currently in the cache']/1024/1024/1024).toFixed(2) + ' GB');
print(' Max bytes configured: ' + (cache['maximum bytes configured']/1024/1024/1024).toFixed(2) + ' GB');
print(' Dirty bytes: ' + (cache['tracked dirty bytes in the cache']/1024/1024).toFixed(2) + ' MB');
}
"
sleep $INTERVAL
done
}
# Calculate operations rate
calculate_ops_rate() {
echo -e "\n[Calculating Operation Rates]"
mongosh --quiet "$MONGO_CONN" --eval "
function getOpCounters() {
return db.serverStatus().opcounters;
}
var before = getOpCounters();
sleep(5000); // 5 second interval
var after = getOpCounters();
print('Operations per second (5s average):');
print(' Insert: ' + ((after.insert - before.insert) / 5));
print(' Query: ' + ((after.query - before.query) / 5));
print(' Update: ' + ((after.update - before.update) / 5));
print(' Delete: ' + ((after.delete - before.delete) / 5));
print(' Command: ' + ((after.command - before.command) / 5));
print(' Total: ' + (
(after.insert - before.insert +
after.query - before.query +
after.update - before.update +
after.delete - before.delete +
after.command - before.command) / 5
));
"
}
# Run monitoring
monitor_performance
calculate_ops_rate
```
## Replication Monitoring
```bash
#!/bin/bash
# MongoDB Replication Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Replication Monitor"
echo "=========================="
# Check replication status
check_replication() {
mongosh --quiet "$MONGO_CONN" --eval "
try {
var status = rs.status();
var config = rs.config();
print('\\nReplica Set: ' + status.set);
print('Version: ' + config.version);
print('Protocol Version: ' + config.protocolVersion);
print('\\nMembers Status:');
print('=' .repeat(80));
// Primary info
var primary = status.members.find(m => m.state === 1);
if (primary) {
print('\\nPRIMARY: ' + primary.name);
print(' Uptime: ' + primary.uptime + ' seconds');
print(' OpTime: ' + primary.optime.ts.getTime());
}
// All members detailed info
status.members.forEach(function(member) {
print('\\nMember: ' + member.name);
print(' State: ' + member.stateStr);
print(' Health: ' + member.health);
print(' Uptime: ' + (member.uptime || 'N/A') + ' seconds');
if (member.state !== 1 && primary) { // If not primary
var lag = primary.optimeDate - member.optimeDate;
print(' Replication Lag: ' + (lag/1000) + ' seconds');
}
print(' Last Heartbeat: ' + (member.lastHeartbeat || 'N/A'));
print(' Ping MS: ' + (member.pingMs || 'N/A'));
if (member.errmsg) {
print(' ERROR: ' + member.errmsg);
}
});
// Oplog information
print('\\n' + '='.repeat(80));
print('\\nOplog Information:');
var oplog = db.getSiblingDB('local').oplog.rs.stats();
print(' Oplog Size: ' + (oplog.size/1024/1024/1024).toFixed(2) + ' GB');
print(' Used Space: ' + (oplog.storageSize/1024/1024/1024).toFixed(2) + ' GB');
print(' Count: ' + oplog.count);
// Get oplog window
var firstOp = db.getSiblingDB('local').oplog.rs.find().sort({ts: 1}).limit(1).toArray()[0];
var lastOp = db.getSiblingDB('local').oplog.rs.find().sort({ts: -1}).limit(1).toArray()[0];
if (firstOp && lastOp) {
var oplogWindow = (lastOp.ts.getTime() - firstOp.ts.getTime()) / 1000 / 3600;
print(' Oplog Window: ' + oplogWindow.toFixed(2) + ' hours');
}
} catch(e) {
print('Error checking replication: ' + e.message);
print('This server may not be part of a replica set.');
}
"
}
# Check for replication issues
check_replication_issues() {
echo -e "\n\nChecking for Replication Issues..."
echo "================================="
mongosh --quiet "$MONGO_CONN" --eval "
try {
var status = rs.status();
var issues = [];
// Check for unhealthy members
status.members.forEach(function(member) {
if (member.health !== 1) {
issues.push('UNHEALTHY: ' + member.name + ' - ' + member.stateStr);
}
// Check for high replication lag
if (member.state === 2) { // Secondary
var primary = status.members.find(m => m.state === 1);
if (primary) {
var lag = (primary.optimeDate - member.optimeDate) / 1000;
if (lag > 60) { // More than 60 seconds
issues.push('HIGH LAG: ' + member.name + ' - ' + lag + ' seconds behind');
}
}
}
// Check for recovering members
if (member.state === 3) {
issues.push('RECOVERING: ' + member.name);
}
});
// Check if there's no primary
if (!status.members.some(m => m.state === 1)) {
issues.push('CRITICAL: No primary elected!');
}
if (issues.length > 0) {
print('\\nISSUES FOUND:');
issues.forEach(function(issue) {
print(' ⚠️ ' + issue);
});
} else {
print('✅ No replication issues detected.');
}
} catch(e) {
print('Error checking for issues: ' + e.message);
}
"
}
# Monitor replication lag over time
monitor_replication_lag() {
echo -e "\n\nMonitoring Replication Lag (30 seconds)..."
echo "========================================"
for i in {1..6}; do
echo -e "\n[$(date '+%Y-%m-%d %H:%M:%S')]"
mongosh --quiet "$MONGO_CONN" --eval "
try {
var status = rs.status();
var primary = status.members.find(m => m.state === 1);
if (primary) {
print('Primary: ' + primary.name);
status.members.forEach(function(member) {
if (member.state === 2) { // Secondary
var lag = (primary.optimeDate - member.optimeDate) / 1000;
print(' ' + member.name + ' lag: ' + lag.toFixed(2) + 's');
}
});
}
} catch(e) {}
"
sleep 5
done
}
# Run all checks
check_replication
check_replication_issues
monitor_replication_lag
```
## Sharding Monitoring
```bash
#!/bin/bash
# MongoDB Sharding Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Sharding Monitor"
echo "======================="
# Check if sharding is enabled
check_sharding_status() {
mongosh --quiet "$MONGO_CONN" --eval "
try {
var configDB = db.getSiblingDB('config');
var adminDB = db.getSiblingDB('admin');
// Check if this is a sharded cluster
var shardingState = adminDB.runCommand({shardingState: 1});
if (!shardingState.enabled) {
print('Sharding is not enabled on this instance.');
return;
}
print('\\nSHARDING STATUS');
print('=' .repeat(80));
// List shards
print('\\nShards:');
configDB.shards.find().forEach(function(shard) {
print(' ' + shard._id + ': ' + shard.host);
print(' State: ' + (shard.state || 'active'));
print(' Tags: ' + (shard.tags || 'none'));
});
// Sharded databases
print('\\nSharded Databases:');
configDB.databases.find({partitioned: true}).forEach(function(db) {
print(' Database: ' + db._id);
print(' Primary Shard: ' + db.primary);
// Collections in this database
configDB.collections.find({_id: {$regex: '^' + db._id + '\\.'}}).forEach(function(coll) {
print('\\n Collection: ' + coll._id);
print(' Shard Key: ' + JSON.stringify(coll.key));
print(' Unique: ' + coll.unique);
// Chunk distribution
var chunkCounts = {};
configDB.chunks.find({ns: coll._id}).forEach(function(chunk) {
chunkCounts[chunk.shard] = (chunkCounts[chunk.shard] || 0) + 1;
});
print(' Chunk Distribution:');
Object.keys(chunkCounts).forEach(function(shard) {
print(' ' + shard + ': ' + chunkCounts[shard] + ' chunks');
});
});
});
// Balancer status
print('\\n' + '='.repeat(80));
print('\\nBalancer Status:');
var balancerStatus = configDB.settings.findOne({_id: 'balancer'});
print(' Mode: ' + (balancerStatus ? balancerStatus.mode : 'full'));
print(' Stopped: ' + (balancerStatus && balancerStatus.stopped ? 'Yes' : 'No'));
// Active migrations
print('\\nActive Migrations:');
var migrations = configDB.migrations.find({}).toArray();
if (migrations.length > 0) {
migrations.forEach(function(migration) {
print(' ' + migration.ns + ': ' + migration.from + ' -> ' + migration.to);
});
} else {
print(' None');
}
} catch(e) {
print('Error checking sharding status: ' + e.message);
}
"
}
# Monitor chunk operations
monitor_chunk_operations() {
echo -e "\n\nMonitoring Chunk Operations..."
echo "============================="
mongosh --quiet "$MONGO_CONN" --eval "
var configDB = db.getSiblingDB('config');
// Recent chunk splits
print('\\nRecent Chunk Splits (last 24 hours):');
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
configDB.changelog.find({
what: 'split',
time: {$gte: yesterday}
}).sort({time: -1}).limit(5).forEach(function(entry) {
print(' ' + entry.time.toISOString() + ' - ' + entry.ns + ' on ' + entry.shard);
});
// Recent migrations
print('\\nRecent Chunk Migrations (last 24 hours):');
configDB.changelog.find({
what: 'moveChunk.from',
time: {$gte: yesterday}
}).sort({time: -1}).limit(5).forEach(function(entry) {
print(' ' + entry.time.toISOString() + ' - ' + entry.ns);
print(' ' + entry.details.from + ' -> ' + entry.details.to);
print(' Status: ' + entry.details.status);
});
// Check for jumbo chunks
print('\\nJumbo Chunks:');
var jumboCount = 0;
configDB.chunks.find({jumbo: true}).forEach(function(chunk) {
print(' ' + chunk.ns + ' - Shard: ' + chunk.shard);
print(' Min: ' + JSON.stringify(chunk.min));
print(' Max: ' + JSON.stringify(chunk.max));
jumboCount++;
});
if (jumboCount === 0) {
print(' No jumbo chunks found');
}
"
}
# Check shard key effectiveness
check_shard_key_effectiveness() {
echo -e "\n\nShard Key Effectiveness Analysis..."
echo "================================="
mongosh --quiet "$MONGO_CONN" --eval "
var configDB = db.getSiblingDB('config');
print('\\nShard Key Analysis:');
configDB.collections.find().forEach(function(coll) {
var totalChunks = configDB.chunks.count({ns: coll._id});
if (totalChunks === 0) return;
print('\\nCollection: ' + coll._id);
print(' Shard Key: ' + JSON.stringify(coll.key));
print(' Total Chunks: ' + totalChunks);
// Check chunk distribution
var shardCounts = {};
var maxChunkSize = 0;
var minChunkSize = Number.MAX_VALUE;
configDB.chunks.find({ns: coll._id}).forEach(function(chunk) {
shardCounts[chunk.shard] = (shardCounts[chunk.shard] || 0) + 1;
});
Object.values(shardCounts).forEach(function(count) {
maxChunkSize = Math.max(maxChunkSize, count);
minChunkSize = Math.min(minChunkSize, count);
});
var imbalance = maxChunkSize - minChunkSize;
var imbalanceRatio = (imbalance / totalChunks * 100).toFixed(2);
print(' Chunk Distribution Imbalance: ' + imbalance + ' chunks (' + imbalanceRatio + '%)');
if (imbalanceRatio > 20) {
print(' ⚠️ WARNING: High imbalance detected!');
}
});
"
}
# Run all sharding checks
check_sharding_status
monitor_chunk_operations
check_shard_key_effectiveness
```
## Storage Monitoring
```bash
#!/bin/bash
# MongoDB Storage Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Storage Monitor"
echo "======================"
# Check storage statistics
check_storage_stats() {
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nSTORAGE STATISTICS');
print('=' .repeat(80));
// Get all databases
db.adminCommand('listDatabases').databases.forEach(function(database) {
var currentDb = db.getSiblingDB(database.name);
var stats = currentDb.stats();
print('\\nDatabase: ' + database.name);
print(' Data Size: ' + (stats.dataSize / 1024 / 1024 / 1024).toFixed(3) + ' GB');
print(' Storage Size: ' + (stats.storageSize / 1024 / 1024 / 1024).toFixed(3) + ' GB');
print(' Index Size: ' + (stats.indexSize / 1024 / 1024 / 1024).toFixed(3) + ' GB');
print(' Total Size: ' + ((stats.dataSize + stats.indexSize) / 1024 / 1024 / 1024).toFixed(3) + ' GB');
print(' Storage Efficiency: ' + ((stats.dataSize / stats.storageSize * 100).toFixed(2)) + '%');
print(' Average Object Size: ' + (stats.avgObjSize || 0).toFixed(0) + ' bytes');
print(' Collections: ' + stats.collections);
print(' Objects: ' + stats.objects.toLocaleString());
// Collection details
if (database.name !== 'local' && database.name !== 'admin') {
print('\\n Top Collections by Size:');
currentDb.getCollectionNames().forEach(function(collName) {
var collStats = currentDb.getCollection(collName).stats();
var totalSize = (collStats.size + collStats.totalIndexSize) / 1024 / 1024;
if (totalSize > 10) { // Only show collections > 10MB
print(' ' + collName + ': ' + totalSize.toFixed(2) + ' MB');
}
});
}
});
"
}
# Monitor disk usage
monitor_disk_usage() {
echo -e "\n\nDisk Usage Analysis..."
echo "===================="
mongosh --quiet "$MONGO_CONN" --eval "
var adminDb = db.getSiblingDB('admin');
var serverStatus = adminDb.serverStatus();
// Get dbPath from server status
var dbPath = adminDb.runCommand({getCmdLineOpts: 1}).parsed.storage.dbPath;
print('\\nDatabase Path: ' + dbPath);
// WiredTiger specific stats
if (serverStatus.storageEngine.name === 'wiredTiger') {
var wtStats = serverStatus.wiredTiger;
print('\\nWiredTiger Cache Statistics:');
var cache = wtStats.cache;
print(' Maximum bytes configured: ' + (cache['maximum bytes configured'] / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Currently in cache: ' + (cache['bytes currently in the cache'] / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Dirty bytes in cache: ' + (cache['tracked dirty bytes in the cache'] / 1024 / 1024).toFixed(2) + ' MB');
print(' Cache used %: ' + ((cache['bytes currently in the cache'] / cache['maximum bytes configured'] * 100).toFixed(2)) + '%');
print('\\nWiredTiger Block Manager:');
var blockManager = wtStats['block-manager'];
print(' Blocks read: ' + blockManager['blocks read'].toLocaleString());
print(' Blocks written: ' + blockManager['blocks written'].toLocaleString());
print(' Bytes read: ' + (blockManager['bytes read'] / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Bytes written: ' + (blockManager['bytes written'] / 1024 / 1024 / 1024).toFixed(2) + ' GB');
}
"
}
# Check for storage warnings
check_storage_warnings() {
echo -e "\n\nStorage Health Check..."
echo "===================="
mongosh --quiet "$MONGO_CONN" --eval "
var warnings = [];
// Check each database
db.adminCommand('listDatabases').databases.forEach(function(database) {
var stats = db.getSiblingDB(database.name).stats();
// Check storage efficiency
var efficiency = stats.dataSize / stats.storageSize * 100;
if (efficiency < 50) {
warnings.push('Low storage efficiency in ' + database.name + ': ' + efficiency.toFixed(2) + '%');
}
// Check for large databases
var totalSizeGB = (stats.dataSize + stats.indexSize) / 1024 / 1024 / 1024;
if (totalSizeGB > 100) {
warnings.push('Large database detected: ' + database.name + ' (' + totalSizeGB.toFixed(2) + ' GB)');
}
// Check index to data ratio
var indexRatio = stats.indexSize / stats.dataSize * 100;
if (indexRatio > 100) {
warnings.push('High index ratio in ' + database.name + ': ' + indexRatio.toFixed(2) + '%');
}
});
// Check WiredTiger cache pressure
var serverStatus = db.serverStatus();
if (serverStatus.storageEngine.name === 'wiredTiger') {
var cache = serverStatus.wiredTiger.cache;
var cacheUsedPct = cache['bytes currently in the cache'] / cache['maximum bytes configured'] * 100;
if (cacheUsedPct > 95) {
warnings.push('High WiredTiger cache usage: ' + cacheUsedPct.toFixed(2) + '%');
}
var dirtyPct = cache['tracked dirty bytes in the cache'] / cache['maximum bytes configured'] * 100;
if (dirtyPct > 20) {
warnings.push('High dirty cache percentage: ' + dirtyPct.toFixed(2) + '%');
}
}
if (warnings.length > 0) {
print('\\n⚠️ WARNINGS DETECTED:');
warnings.forEach(function(warning) {
print(' - ' + warning);
});
} else {
print('\\n✅ No storage warnings detected.');
}
"
}
# Run all storage checks
check_storage_stats
monitor_disk_usage
check_storage_warnings
```
## Connection Monitoring
```bash
#!/bin/bash
# MongoDB Connection Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Connection Monitor"
echo "========================="
# Monitor current connections
monitor_connections() {
mongosh --quiet "$MONGO_CONN" --eval "
var serverStatus = db.serverStatus();
var connections = serverStatus.connections;
print('\\nCONNECTION OVERVIEW');
print('=' .repeat(80));
print('Current Connections: ' + connections.current);
print('Available Connections: ' + connections.available);
print('Total Created: ' + connections.totalCreated);
print('Connection Usage: ' + (connections.current / (connections.current + connections.available) * 100).toFixed(2) + '%');
// Network statistics
var network = serverStatus.network;
print('\\nNETWORK STATISTICS');
print('Bytes In: ' + (network.bytesIn / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print('Bytes Out: ' + (network.bytesOut / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print('Num Requests: ' + network.numRequests.toLocaleString());
// Get current operations grouped by client
print('\\nACTIVE CONNECTIONS BY CLIENT');
print('-' .repeat(80));
var clientOps = {};
db.currentOp(true).inprog.forEach(function(op) {
if (op.client) {
var client = op.client.split(':')[0];
if (!clientOps[client]) {
clientOps[client] = {
count: 0,
operations: []
};
}
clientOps[client].count++;
if (op.op && op.op !== 'none') {
clientOps[client].operations.push(op.op);
}
}
});
Object.keys(clientOps).sort().forEach(function(client) {
var info = clientOps[client];
print('\\nClient: ' + client);
print(' Active Operations: ' + info.count);
if (info.operations.length > 0) {
var opCounts = {};
info.operations.forEach(function(op) {
opCounts[op] = (opCounts[op] || 0) + 1;
});
print(' Operation Types: ' + JSON.stringify(opCounts));
}
});
// Connection pool stats
print('\\n' + '=' .repeat(80));
print('\\nCONNECTION DETAILS');
// Get all current connections
var currentOps = db.currentOp(true).inprog;
var connectionTypes = {};
var longRunning = [];
currentOps.forEach(function(op) {
// Categorize connections
var type = op.desc || 'unknown';
if (type.includes('conn')) type = 'client';
else if (type.includes('repl')) type = 'replication';
else if (type.includes('TTLMonitor')) type = 'ttl';
connectionTypes[type] = (connectionTypes[type] || 0) + 1;
// Check for long-running operations
if (op.active && op.secs_running > 60) {
longRunning.push({
opid: op.opid,
ns: op.ns || 'N/A',
op: op.op || 'N/A',
running: op.secs_running,
client: op.client || 'N/A'
});
}
});
print('\\nConnection Types:');
Object.keys(connectionTypes).forEach(function(type) {
print(' ' + type + ': ' + connectionTypes[type]);
});
if (longRunning.length > 0) {
print('\\nLONG-RUNNING OPERATIONS (>60s):');
longRunning.forEach(function(op) {
print(' OpID: ' + op.opid);
print(' Namespace: ' + op.ns);
print(' Operation: ' + op.op);
print(' Running Time: ' + op.running + ' seconds');
print(' Client: ' + op.client);
});
}
"
}
# Monitor connection changes over time
monitor_connection_changes() {
echo -e "\n\nMonitoring Connection Changes (30 seconds)..."
echo "==========================================="
for i in {1..6}; do
echo -e "\n[$(date '+%Y-%m-%d %H:%M:%S')]"
mongosh --quiet "$MONGO_CONN" --eval "
var conns = db.serverStatus().connections;
print('Connections: ' + conns.current + '/' + (conns.current + conns.available));
// Show top operations
var ops = db.currentOp().inprog.filter(function(op) {
return op.active && op.op !== 'none';
});
if (ops.length > 0) {
print('Active Ops: ' + ops.length);
ops.slice(0, 3).forEach(function(op) {
print(' - ' + op.op + ' on ' + (op.ns || 'N/A') +
' (' + (op.secs_running || 0) + 's)');
});
}
"
sleep 5
done
}
# Run connection monitoring
monitor_connections
monitor_connection_changes
```
## Query Performance Monitoring
```bash
#!/bin/bash
# MongoDB Query Performance Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Query Performance Monitor"
echo "================================"
# Analyze slow queries
analyze_slow_queries() {
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nSLOW QUERY ANALYSIS');
print('=' .repeat(80));
// Get profiling level for each database
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
var profilingLevel = currentDb.getProfilingStatus();
print('\\nDatabase: ' + database.name);
print(' Profiling Level: ' + profilingLevel.was);
print(' Slow MS Threshold: ' + profilingLevel.slowms);
if (profilingLevel.was > 0) {
// Get slow queries from system.profile
var slowQueries = currentDb.system.profile.find({
millis: {$gt: profilingLevel.slowms}
}).sort({ts: -1}).limit(10).toArray();
if (slowQueries.length > 0) {
print('\\n Recent Slow Queries:');
slowQueries.forEach(function(query) {
print('\\n Timestamp: ' + query.ts);
print(' Operation: ' + query.op);
print(' Namespace: ' + query.ns);
print(' Duration: ' + query.millis + 'ms');
print(' Examined: ' + (query.docsExamined || 0) + ' docs');
print(' Returned: ' + (query.nreturned || 0) + ' docs');
print(' Index Used: ' + (query.planSummary || 'UNKNOWN'));
if (query.command) {
print(' Command: ' + JSON.stringify(query.command).substring(0, 100) + '...');
}
});
} else {
print('\\n No slow queries found in profile collection');
}
} else {
print('\\n ⚠️ Profiling is disabled for this database');
}
});
"
}
# Check current operations
check_current_operations() {
echo -e "\n\nCurrent Operations Analysis..."
echo "============================="
mongosh --quiet "$MONGO_CONN" --eval "
var currentOps = db.currentOp().inprog;
print('Total Operations: ' + currentOps.length);
// Filter and categorize operations
var activeOps = currentOps.filter(function(op) {
return op.active && op.op !== 'none';
});
print('Active Operations: ' + activeOps.length);
if (activeOps.length > 0) {
print('\\nACTIVE OPERATIONS:');
print('-' .repeat(80));
activeOps.sort(function(a, b) {
return (b.secs_running || 0) - (a.secs_running || 0);
}).slice(0, 10).forEach(function(op) {
print('\\nOperation ID: ' + op.opid);
print(' Type: ' + op.op);
print(' Namespace: ' + (op.ns || 'N/A'));
print(' Running Time: ' + (op.secs_running || 0) + ' seconds');
print(' Client: ' + (op.client || 'N/A'));
if (op.command) {
var cmdStr = JSON.stringify(op.command);
print(' Command: ' + cmdStr.substring(0, 200) + (cmdStr.length > 200 ? '...' : ''));
}
if (op.planSummary) {
print(' Plan: ' + op.planSummary);
}
if (op.progress) {
print(' Progress: ' + JSON.stringify(op.progress));
}
// Highlight potential issues
if (op.secs_running > 300) {
print(' ⚠️ WARNING: Long running operation!');
}
if (op.waitingForLock) {
print(' ⚠️ WARNING: Waiting for lock!');
}
});
} else {
print('\\n✅ No active operations found');
}
// Check for lock waits
var waitingOps = currentOps.filter(function(op) {
return op.waitingForLock;
});
if (waitingOps.length > 0) {
print('\\n⚠️ OPERATIONS WAITING FOR LOCKS: ' + waitingOps.length);
waitingOps.slice(0, 5).forEach(function(op) {
print(' - ' + op.op + ' on ' + (op.ns || 'N/A'));
});
}
"
}
# Query patterns analysis
analyze_query_patterns() {
echo -e "\n\nQuery Pattern Analysis..."
echo "========================"
mongosh --quiet "$MONGO_CONN" --eval "
// This requires profiling to be enabled
print('\\nANALYZING QUERY PATTERNS');
print('(Requires profiling level 1 or 2)');
print('-' .repeat(80));
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
var profilingLevel = currentDb.getProfilingStatus();
if (profilingLevel.was > 0) {
print('\\nDatabase: ' + database.name);
// Aggregate query patterns
var patterns = currentDb.system.profile.aggregate([
{$match: {op: {$in: ['query', 'find', 'aggregate', 'count', 'distinct']}}},
{$group: {
_id: {
ns: '$ns',
op: '$op',
planSummary: '$planSummary'
},
count: {$sum: 1},
avgMillis: {$avg: '$millis'},
maxMillis: {$max: '$millis'},
avgDocsExamined: {$avg: '$docsExamined'},
avgDocsReturned: {$avg: '$nreturned'}
}},
{$sort: {count: -1}},
{$limit: 10}
]).toArray();
if (patterns.length > 0) {
print('\\n Top Query Patterns:');
patterns.forEach(function(pattern, idx) {
print('\\n ' + (idx + 1) + '. Namespace: ' + pattern._id.ns);
print(' Operation: ' + pattern._id.op);
print(' Plan: ' + (pattern._id.planSummary || 'N/A'));
print(' Count: ' + pattern.count);
print(' Avg Duration: ' + pattern.avgMillis.toFixed(2) + 'ms');
print(' Max Duration: ' + pattern.maxMillis + 'ms');
print(' Avg Docs Examined: ' + pattern.avgDocsExamined.toFixed(0));
print(' Avg Docs Returned: ' + pattern.avgDocsReturned.toFixed(0));
// Calculate efficiency
if (pattern.avgDocsExamined > 0) {
var efficiency = (pattern.avgDocsReturned / pattern.avgDocsExamined * 100);
print(' Efficiency: ' + efficiency.toFixed(2) + '%');
if (efficiency < 50) {
print(' ⚠️ Low efficiency - consider adding an index');
}
}
});
}
}
});
"
}
# Run all query performance checks
analyze_slow_queries
check_current_operations
analyze_query_patterns
```
## Index Monitoring
```bash
#!/bin/bash
# MongoDB Index Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Index Monitor"
echo "===================="
# Analyze index usage and effectiveness
analyze_indexes() {
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nINDEX ANALYSIS');
print('=' .repeat(80));
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
print('\\nDatabase: ' + database.name);
currentDb.getCollectionNames().forEach(function(collName) {
var coll = currentDb.getCollection(collName);
var indexes = coll.getIndexes();
if (indexes.length > 1) { // More than just _id index
print('\\n Collection: ' + collName);
print(' Total Indexes: ' + indexes.length);
var totalIndexSize = 0;
var stats = coll.stats();
indexes.forEach(function(index) {
print('\\n Index: ' + index.name);
print(' Keys: ' + JSON.stringify(index.key));
if (index.unique) print(' Unique: true');
if (index.sparse) print(' Sparse: true');
if (index.partialFilterExpression) {
print(' Partial: ' + JSON.stringify(index.partialFilterExpression));
}
// Get index stats if available
try {
var indexStats = coll.aggregate([
{$indexStats: {}},
{$match: {name: index.name}}
]).toArray()[0];
if (indexStats) {
print(' Usage Count: ' + indexStats.accesses.ops);
print(' Last Used: ' + (indexStats.accesses.since || 'Never'));
// Calculate days since last use
if (indexStats.accesses.since) {
var daysSinceUse = (new Date() - indexStats.accesses.since) / (1000 * 60 * 60 * 24);
if (daysSinceUse > 30) {
print(' ⚠️ WARNING: Not used in ' + daysSinceUse.toFixed(0) + ' days');
}
}
if (indexStats.accesses.ops === 0) {
print(' ⚠️ WARNING: Unused index');
}
}
} catch(e) {
// Index stats not available
}
});
// Check for redundant indexes
print('\\n Checking for redundant indexes...');
for (var i = 0; i < indexes.length; i++) {
for (var j = i + 1; j < indexes.length; j++) {
var keys1 = Object.keys(indexes[i].key);
var keys2 = Object.keys(indexes[j].key);
// Check if one index is a prefix of another
var isPrefix = true;
if (keys1.length <= keys2.length) {
for (var k = 0; k < keys1.length; k++) {
if (keys1[k] !== keys2[k]) {
isPrefix = false;
break;
}
}
if (isPrefix) {
print(' ⚠️ Potential redundancy: ' + indexes[i].name + ' is a prefix of ' + indexes[j].name);
}
}
}
}
}
});
});
"
}
# Find missing indexes based on query patterns
find_missing_indexes() {
echo -e "\n\nMissing Index Analysis..."
echo "========================"
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nCHECKING FOR MISSING INDEXES');
print('(Based on slow queries without index usage)');
print('-' .repeat(80));
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
var profilingLevel = currentDb.getProfilingStatus();
if (profilingLevel.was > 0) {
// Find queries that did collection scans
var collScans = currentDb.system.profile.find({
planSummary: 'COLLSCAN',
millis: {$gt: 100} // Only queries taking more than 100ms
}).sort({millis: -1}).limit(10).toArray();
if (collScans.length > 0) {
print('\\nDatabase: ' + database.name);
print('\\nQueries performing collection scans:');
var suggestions = {};
collScans.forEach(function(query) {
print('\\n Namespace: ' + query.ns);
print(' Duration: ' + query.millis + 'ms');
print(' Documents Examined: ' + (query.docsExamined || 'N/A'));
// Extract filter fields for index suggestions
if (query.command && query.command.filter) {
var filterKeys = Object.keys(query.command.filter);
var indexSuggestion = {};
filterKeys.forEach(function(key) {
if (!key.startsWith('$')) {
indexSuggestion[key] = 1;
}
});
if (Object.keys(indexSuggestion).length > 0) {
var suggestionKey = query.ns + ':' + JSON.stringify(indexSuggestion);
suggestions[suggestionKey] = (suggestions[suggestionKey] || 0) + 1;
}
}
});
if (Object.keys(suggestions).length > 0) {
print('\\n📌 INDEX SUGGESTIONS:');
Object.keys(suggestions).forEach(function(suggestion) {
var parts = suggestion.split(':');
print(' Collection: ' + parts[0]);
print(' Suggested Index: ' + parts[1]);
print(' Would help ' + suggestions[suggestion] + ' slow queries\\n');
});
}
}
}
});
"
}
# Index size analysis
analyze_index_sizes() {
echo -e "\n\nIndex Size Analysis..."
echo "===================="
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nINDEX SIZE BREAKDOWN');
print('-' .repeat(80));
var totalIndexSize = 0;
var largeIndexes = [];
db.adminCommand('listDatabases').databases.forEach(function(database) {
if (database.name === 'local' || database.name === 'config') return;
var currentDb = db.getSiblingDB(database.name);
var dbIndexSize = 0;
currentDb.getCollectionNames().forEach(function(collName) {
var stats = currentDb.getCollection(collName).stats();
if (stats.indexSizes) {
Object.keys(stats.indexSizes).forEach(function(indexName) {
var indexSizeMB = stats.indexSizes[indexName] / 1024 / 1024;
dbIndexSize += indexSizeMB;
if (indexSizeMB > 100) { // Indexes larger than 100MB
largeIndexes.push({
db: database.name,
collection: collName,
index: indexName,
size: indexSizeMB
});
}
});
}
});
if (dbIndexSize > 0) {
print('\\n' + database.name + ': ' + dbIndexSize.toFixed(2) + ' MB');
totalIndexSize += dbIndexSize;
}
});
print('\\nTotal Index Size: ' + totalIndexSize.toFixed(2) + ' MB');
if (largeIndexes.length > 0) {
print('\\nLarge Indexes (>100MB):');
largeIndexes.sort(function(a, b) { return b.size - a.size; }).forEach(function(idx) {
print(' ' + idx.db + '.' + idx.collection + '.' + idx.index + ': ' + idx.size.toFixed(2) + ' MB');
});
}
"
}
# Run all index checks
analyze_indexes
find_missing_indexes
analyze_index_sizes
```
## OpLog Monitoring
```bash
#!/bin/bash
# MongoDB OpLog Monitoring Script
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB OpLog Monitor"
echo "===================="
# Monitor oplog status and size
monitor_oplog() {
mongosh --quiet "$MONGO_CONN" --eval "
print('\\nOPLOG STATUS');
print('=' .repeat(80));
try {
var localDb = db.getSiblingDB('local');
var oplog = localDb.oplog.rs;
// Check if oplog exists (replica set member)
if (!oplog.exists()) {
print('This instance is not running as a replica set member.');
return;
}
// Oplog stats
var stats = oplog.stats();
print('\\nOplog Collection Stats:');
print(' Size: ' + (stats.size / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Storage Size: ' + (stats.storageSize / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Count: ' + stats.count.toLocaleString() + ' operations');
print(' Average Object Size: ' + stats.avgObjSize + ' bytes');
// Get first and last oplog entries
var firstOp = oplog.find().sort({ts: 1}).limit(1).toArray()[0];
var lastOp = oplog.find().sort({ts: -1}).limit(1).toArray()[0];
if (firstOp && lastOp) {
print('\\nOplog Time Range:');
print(' First Operation: ' + firstOp.ts.toString());
print(' Last Operation: ' + lastOp.ts.toString());
// Calculate oplog window
var timeDiff = lastOp.ts.getTime() - firstOp.ts.getTime();
var hours = timeDiff / 1000 / 3600;
print(' Oplog Window: ' + hours.toFixed(2) + ' hours');
if (hours < 24) {
print(' ⚠️ WARNING: Oplog window is less than 24 hours!');
}
// Calculate oplog growth rate
var recentOps = oplog.find({
ts: {$gte: new Timestamp(lastOp.ts.getTime() - 3600, 0)}
}).count();
print('\\nOplog Growth Rate:');
print(' Operations in last hour: ' + recentOps.toLocaleString());
print(' Estimated daily operations: ' + (recentOps * 24).toLocaleString());
// Estimate how long current oplog will last
var opsPerHour = recentOps;
var totalCapacity = stats.maxSize / stats.avgObjSize;
var hoursRemaining = (totalCapacity - stats.count) / opsPerHour;
print('\\nOplog Capacity:');
print(' Max Size: ' + (stats.maxSize / 1024 / 1024 / 1024).toFixed(2) + ' GB');
print(' Current Usage: ' + ((stats.size / stats.maxSize) * 100).toFixed(2) + '%');
print(' Estimated Hours Until Full: ' + hoursRemaining.toFixed(2));
if (hoursRemaining < 48) {
print(' ⚠️ WARNING: Oplog may fill up in less than 48 hours!');
}
}
// Analyze oplog operations
print('\\nOplog Operation Analysis (last 1000 operations):');
var opTypes = {};
var nsByOp = {};
oplog.find().sort({ts: -1}).limit(1000).forEach(function(op) {
opTypes[op.op] = (opTypes[op.op] || 0) + 1;
if (op.ns) {
if (!nsByOp[op.ns]) nsByOp[op.ns] = {};
nsByOp[op.ns][op.op] = (nsByOp[op.ns][op.op] || 0) + 1;
}
});
print('\\nOperation Types:');
Object.keys(opTypes).forEach(function(opType) {
var opName = {
'i': 'insert',
'u': 'update',
'd': 'delete',
'c': 'command',
'n': 'noop'
}[opType] || opType;
print(' ' + opName + ': ' + opTypes[opType] + ' (' +
(opTypes[opType] / 10).toFixed(2) + '%)');
});
// Top namespaces by operation count
print('\\nTop Namespaces by Activity:');
var nsArray = [];
Object.keys(nsByOp).forEach(function(ns) {
var total = 0;
Object.values(nsByOp[ns]).forEach(function(count) {
total += count;
});
nsArray.push({ns: ns, count: total, ops: nsByOp[ns]});
});
nsArray.sort(function(a, b) { return b.count - a.count; })
.slice(0, 5)
.forEach(function(item) {
print(' ' + item.ns + ': ' + item.count + ' operations');
});
} catch(e) {
print('Error analyzing oplog: ' + e.message);
}
"
}
# Monitor replication lag based on oplog
monitor_replication_via_oplog() {
echo -e "\n\nReplication Lag Analysis via OpLog..."
echo "===================================="
mongosh --quiet "$MONGO_CONN" --eval "
try {
var replStatus = rs.status();
if (!replStatus.ok) {
print('Not running in replica set mode');
return;
}
print('\\nMember OpLog Status:');
print('-' .repeat(80));
var primary = replStatus.members.find(m => m.state === 1);
replStatus.members.forEach(function(member) {
print('\\nMember: ' + member.name);
print(' State: ' + member.stateStr);
if (member.optime) {
print(' OpTime: ' + member.optime.ts.toString());
print(' OpTime Date: ' + member.optimeDate);
if (primary && member._id !== primary._id) {
var lagSeconds = (primary.optimeDate - member.optimeDate) / 1000;
print(' Replication Lag: ' + lagSeconds + ' seconds');
if (lagSeconds > 60) {
print(' ⚠️ WARNING: High replication lag detected!');
}
}
}
if (member.lastHeartbeat) {
var heartbeatLag = (new Date() - member.lastHeartbeat) / 1000;
if (heartbeatLag > 10) {
print(' ⚠️ WARNING: Last heartbeat was ' + heartbeatLag.toFixed(0) + ' seconds ago');
}
}
});
} catch(e) {
print('Error: ' + e.message);
}
"
}
# Run oplog monitoring
monitor_oplog
monitor_replication_via_oplog
```
## Alert Script
```bash
#!/bin/bash
# MongoDB Alert Monitoring Script
# This script checks for various issues and can send alerts
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
ALERT_EMAIL="${ALERT_EMAIL:-admin@example.com}"
ALERT_THRESHOLD_CPU=80
ALERT_THRESHOLD_MEM=90
ALERT_THRESHOLD_CONNECTIONS=80
ALERT_THRESHOLD_REPL_LAG=300 # 5 minutes
echo "MongoDB Alert Monitor"
echo "===================="
# Function to send alert (customize based on your alerting system)
send_alert() {
local severity=$1
local message=$2
echo "[${severity}] ${message}"
# Example: Send email alert
# echo "${message}" | mail -s "MongoDB Alert: ${severity}" "${ALERT_EMAIL}"
# Example: Send to monitoring system
# curl -X POST "http://monitoring-system/alert" \
# -d "{\"severity\":\"${severity}\",\"message\":\"${message}\"}"
}
# Comprehensive alert checking
check_all_alerts() {
mongosh --quiet "$MONGO_CONN" --eval "
var alerts = [];
var warnings = [];
var info = [];
try {
// Server status
var status = db.serverStatus();
// 1. Check connections
var connPct = status.connections.current /
(status.connections.current + status.connections.available) * 100;
if (connPct > ${ALERT_THRESHOLD_CONNECTIONS}) {
alerts.push('High connection usage: ' + connPct.toFixed(2) + '%');
} else if (connPct > 70) {
warnings.push('Connection usage at ' + connPct.toFixed(2) + '%');
}
// 2. Check memory
var memUsageGB = status.mem.resident / 1024;
var virtualGB = status.mem.virtual / 1024;
if (virtualGB > memUsageGB * 2) {
warnings.push('Virtual memory is ' + (virtualGB/memUsageGB).toFixed(2) +
'x resident memory');
}
// 3. Check WiredTiger cache
if (status.wiredTiger) {
var cache = status.wiredTiger.cache;
var cacheUsedPct = cache['bytes currently in the cache'] /
cache['maximum bytes configured'] * 100;
if (cacheUsedPct > 95) {
alerts.push('WiredTiger cache usage critical: ' +
cacheUsedPct.toFixed(2) + '%');
} else if (cacheUsedPct > 80) {
warnings.push('WiredTiger cache usage high: ' +
cacheUsedPct.toFixed(2) + '%');
}
// Check dirty cache
var dirtyPct = cache['tracked dirty bytes in the cache'] /
cache['maximum bytes configured'] * 100;
if (dirtyPct > 20) {
warnings.push('High dirty cache: ' + dirtyPct.toFixed(2) + '%');
}
}
// 4. Check replication
try {
var replStatus = rs.status();
if (replStatus.ok) {
var primary = replStatus.members.find(m => m.state === 1);
// Check if no primary
if (!primary) {
alerts.push('CRITICAL: No primary in replica set!');
}
// Check member health and lag
replStatus.members.forEach(function(member) {
if (member.health !== 1) {
alerts.push('Member ' + member.name + ' is unhealthy: ' +
member.stateStr);
}
if (member.state === 2 && primary) { // Secondary
var lag = (primary.optimeDate - member.optimeDate) / 1000;
if (lag > ${ALERT_THRESHOLD_REPL_LAG}) {
alerts.push('High replication lag on ' + member.name +
': ' + lag + ' seconds');
} else if (lag > 60) {
warnings.push('Replication lag on ' + member.name +
': ' + lag + ' seconds');
}
}
});
// Check oplog window
var oplog = db.getSiblingDB('local').oplog.rs;
var firstOp = oplog.find().sort({ts: 1}).limit(1).toArray()[0];
var lastOp = oplog.find().sort({ts: -1}).limit(1).toArray()[0];
if (firstOp && lastOp) {
var oplogHours = (lastOp.ts.getTime() - firstOp.ts.getTime()) /
1000 / 3600;
if (oplogHours < 24) {
alerts.push('Oplog window less than 24 hours: ' +
oplogHours.toFixed(2) + ' hours');
} else if (oplogHours < 48) {
warnings.push('Oplog window is ' + oplogHours.toFixed(2) +
' hours');
}
}
}
} catch(e) {
// Not a replica set
}
// 5. Check disk space for each database
db.adminCommand('listDatabases').databases.forEach(function(database) {
var stats = db.getSiblingDB(database.name).stats();
var efficiency = stats.dataSize / stats.storageSize * 100;
if (efficiency < 50 && stats.dataSize > 1024 * 1024 * 1024) {
warnings.push('Low storage efficiency in ' + database.name +
': ' + efficiency.toFixed(2) + '%');
}
});
// 6. Check for long running operations
var longOps = db.currentOp().inprog.filter(function(op) {
return op.active && op.secs_running > 300; // 5 minutes
});
if (longOps.length > 0) {
longOps.forEach(function(op) {
warnings.push('Long running operation: ' + op.op + ' on ' +
(op.ns || 'N/A') + ' (' + op.secs_running + 's)');
});
}
// 7. Check for lock waits
var waitingOps = db.currentOp().inprog.filter(function(op) {
return op.waitingForLock;
});
if (waitingOps.length > 10) {
alerts.push('High number of operations waiting for locks: ' +
waitingOps.length);
} else if (waitingOps.length > 5) {
warnings.push('Operations waiting for locks: ' + waitingOps.length);
}
// Output results
if (alerts.length > 0) {
print('\\nCRITICAL ALERTS:');
print('================');
alerts.forEach(function(alert) {
print('🚨 ' + alert);
});
}
if (warnings.length > 0) {
print('\\nWARNINGS:');
print('=========');
warnings.forEach(function(warning) {
print('⚠️ ' + warning);
});
}
if (info.length > 0) {
print('\\nINFO:');
print('=====');
info.forEach(function(i) {
print('ℹ️ ' + i);
});
}
if (alerts.length === 0 && warnings.length === 0) {
print('\\n✅ All systems operational - no alerts');
}
// Return alert summary
return {
critical: alerts.length,
warning: warnings.length,
info: info.length
};
} catch(e) {
print('Error running alert checks: ' + e.message);
}
"
}
# Run alert checks
check_all_alerts
# You can schedule this script in cron for regular monitoring:
# */5 * * * * /path/to/mongodb_alert_monitor.sh >> /var/log/mongodb-alerts.log 2>&1
```
## Master Dashboard Script
```bash
#!/bin/bash
# MongoDB Monitoring Dashboard
# This script provides a real-time dashboard view
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
REFRESH_INTERVAL=5
# Function to clear screen and reset cursor
clear_screen() {
clear
tput cup 0 0
}
# Main dashboard loop
show_dashboard() {
while true; do
clear_screen
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
echo "║ MongoDB Real-Time Dashboard ║"
echo "║ $(date '+%Y-%m-%d %H:%M:%S') ║"
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
mongosh --quiet "$MONGO_CONN" --eval "
try {
var status = db.serverStatus();
var replStatus = null;
try {
replStatus = rs.status();
} catch(e) {}
// Server Info
print('\\n┌─ SERVER INFO ────────────────────────────────────────────────────┐');
print('│ Host: ' + status.host.padEnd(58) + '│');
print('│ Version: ' + status.version.padEnd(55) + '│');
print('│ Uptime: ' + (Math.floor(status.uptime/3600) + ' hours').padEnd(56) + '│');
print('└──────────────────────────────────────────────────────────────────┘');
// Connections
var connPct = (status.connections.current /
(status.connections.current + status.connections.available) * 100);
print('\\n┌─ CONNECTIONS ────────────────────────────────────────────────────┐');
print('│ Current: ' + status.connections.current.toString().padEnd(55) + '│');
print('│ Available: ' + status.connections.available.toString().padEnd(53) + '│');
print('│ Usage: ' + connPct.toFixed(2) + '%'.padEnd(57) + '│');
print('└──────────────────────────────────────────────────────────────────┘');
// Memory
print('\\n┌─ MEMORY ─────────────────────────────────────────────────────────┐');
print('│ Resident: ' + (status.mem.resident/1024).toFixed(2) + ' GB'.padEnd(53) + '│');
print('│ Virtual: ' + (status.mem.virtual/1024).toFixed(2) + ' GB'.padEnd(54) + '│');
if (status.wiredTiger) {
var cache = status.wiredTiger.cache;
var cacheGB = (cache['bytes currently in the cache']/1024/1024/1024).toFixed(2);
var maxCacheGB = (cache['maximum bytes configured']/1024/1024/1024).toFixed(2);
print('│ WT Cache: ' + cacheGB + '/' + maxCacheGB + ' GB'.padEnd(53) + '│');
}
print('└──────────────────────────────────────────────────────────────────┘');
// Operations
var ops = status.opcounters;
print('\\n┌─ OPERATIONS (total since startup) ───────────────────────────────┐');
print('│ Insert: ' + ops.insert.toLocaleString().padEnd(56) + '│');
print('│ Query: ' + ops.query.toLocaleString().padEnd(57) + '│');
print('│ Update: ' + ops.update.toLocaleString().padEnd(56) + '│');
print('│ Delete: ' + ops.delete.toLocaleString().padEnd(56) + '│');
print('└──────────────────────────────────────────────────────────────────┘');
// Replication Status
if (replStatus && replStatus.ok) {
print('\\n┌─ REPLICATION ────────────────────────────────────────────────────┐');
print('│ Replica Set: ' + replStatus.set.padEnd(51) + '│');
var primary = replStatus.members.find(m => m.state === 1);
if (primary) {
print('│ Primary: ' + primary.name.padEnd(55) + '│');
}
// Show secondaries with lag
replStatus.members.forEach(function(member) {
if (member.state === 2 && primary) {
var lag = Math.round((primary.optimeDate - member.optimeDate) / 1000);
var lagStr = member.name + ' (lag: ' + lag + 's)';
print('│ Secondary: ' + lagStr.padEnd(53) + '│');
}
});
print('└──────────────────────────────────────────────────────────────────┘');
}
// Active Operations Summary
var currentOps = db.currentOp().inprog;
var activeOps = currentOps.filter(op => op.active && op.op !== 'none');
print('\\n┌─ ACTIVE OPERATIONS ──────────────────────────────────────────────┐');
print('│ Total Active: ' + activeOps.length.toString().padEnd(50) + '│');
if (activeOps.length > 0) {
// Group by operation type
var opTypes = {};
activeOps.forEach(function(op) {
opTypes[op.op] = (opTypes[op.op] || 0) + 1;
});
Object.keys(opTypes).forEach(function(type) {
print('│ ' + type + ': ' + opTypes[type].toString().padEnd(59) + '│');
});
}
print('└──────────────────────────────────────────────────────────────────┘');
} catch(e) {
print('Error: ' + e.message);
}
"
echo -e "\n[Refreshing every ${REFRESH_INTERVAL} seconds. Press Ctrl+C to exit]"
sleep $REFRESH_INTERVAL
done
}
# Run dashboard
show_dashboard
```
## Quick Health Check Script
```bash
#!/bin/bash
# MongoDB Quick Health Check
# Run this for a rapid assessment of MongoDB health
MONGO_CONN="${MONGO_CONN:-mongodb://localhost:27017/admin}"
echo "MongoDB Quick Health Check"
echo "========================="
echo "Timestamp: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
mongosh --quiet "$MONGO_CONN" --eval "
try {
var status = db.serverStatus();
var issues = [];
// Quick checks
print('✓ MongoDB is responding');
// Connection check
var connPct = status.connections.current /
(status.connections.current + status.connections.available) * 100;
if (connPct > 80) {
issues.push('High connection usage: ' + connPct.toFixed(2) + '%');
} else {
print('✓ Connection usage healthy: ' + connPct.toFixed(2) + '%');
}
// Memory check
if (status.wiredTiger) {
var cache = status.wiredTiger.cache;
var cacheUsed = cache['bytes currently in the cache'] /
cache['maximum bytes configured'] * 100;
if (cacheUsed > 95) {
issues.push('Cache usage critical: ' + cacheUsed.toFixed(2) + '%');
} else {
print('✓ Cache usage healthy: ' + cacheUsed.toFixed(2) + '%');
}
}
// Replication check
try {
var replStatus = rs.status();
var primary = replStatus.members.find(m => m.state === 1);
if (!primary) {
issues.push('No primary in replica set!');
} else {
print('✓ Replica set has primary');
// Check for lag
var maxLag = 0;
replStatus.members.forEach(function(member) {
if (member.state === 2) {
var lag = (primary.optimeDate - member.optimeDate) / 1000;
maxLag = Math.max(maxLag, lag);
}
});
if (maxLag > 60) {
issues.push('High replication lag: ' + maxLag + ' seconds');
} else {
print('✓ Replication lag acceptable: ' + maxLag + ' seconds');
}
}
} catch(e) {
print('✓ Not a replica set (standalone mode)');
}
// Long operations check
var longOps = db.currentOp().inprog.filter(function(op) {
return op.active && op.secs_running > 60;
});
if (longOps.length > 0) {
issues.push(longOps.length + ' long-running operations (>60s)');
} else {
print('✓ No long-running operations');
}
// Summary
print('\\n' + '='.repeat(50));
if (issues.length === 0) {
print('OVERALL STATUS: ✅ HEALTHY');
} else {
print('OVERALL STATUS: ⚠️ ISSUES DETECTED');
print('\\nIssues:');
issues.forEach(function(issue) {
print(' - ' + issue);
});
}
} catch(e) {
print('❌ ERROR: ' + e.message);
}
"
```
These monitoring scripts provide comprehensive coverage of all MongoDB aspects:
1. **Master Monitoring** - Overall system health
2. **Performance Monitoring** - Real-time performance metrics
3. **Replication Monitoring** - Replica set health and lag
4. **Sharding Monitoring** - Shard distribution and balancer
5. **Storage Monitoring** - Disk usage and efficiency
6. **Connection Monitoring** - Client connections and operations
7. **Query Performance** - Slow queries and patterns
8. **Index Monitoring** - Index usage and effectiveness
9. **OpLog Monitoring** - OpLog health and capacity
10. **Alert Script** - Automated alerting for issues
11. **Dashboard Script** - Real-time visual monitoring
12. **Quick Health Check** - Rapid health assessment
You can save these scripts and run them individually or set them up in cron for automated monitoring. They're designed to work with MongoDB 4.x and later versions.
4 comments:
Hi there,
I have a short question:
If I want to list my BI-Users via "mongobiuser list" the following error comes up:
#####
MONGOBI > mongobiuser list
panic: runtime error: index out of range
goroutine 1 [running]:
github.com/10gen/bi-connector/schematools/mongobiuser.MaskUrl(0xc820016613, 0x22, 0x0, 0x0)
/home/vagrant/biconnector/schematools/.gopath/src/github.com/10gen/bi-connector/schematools/mongobiuser/list.go:105 +0x4b5
github.com/10gen/bi-connector/schematools/mongobiuser.getUser(0xc82002c060, 0xc8200ec7b0, 0x8, 0x0, 0x0, 0x0)
/home/vagrant/biconnector/schematools/.gopath/src/github.com/10gen/bi-connector/schematools/mongobiuser/list.go:93 +0x8ba
github.com/10gen/bi-connector/schematools/mongobiuser.(*ListCommand).Execute(0xc82002c060, 0xc82000a5c0, 0x1, 0x2, 0x0, 0x0)
/home/vagrant/biconnector/schematools/.gopath/src/github.com/10gen/bi-connector/schematools/mongobiuser/list.go:38 +0x31f
github.com/jessevdk/go-flags.(*Parser).ParseArgs(0xc82006c1e0, 0xc82000a1c0, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0)
/home/vagrant/biconnector/schematools/vendor/src/github.com/jessevdk/go-flags/parser.go:301 +0xa16
github.com/10gen/bi-connector/schematools/mongobiuser.Execute(0xc82000a1c0, 0x2, 0x2, 0x0, 0x0)
/home/vagrant/biconnector/schematools/.gopath/src/github.com/10gen/bi-connector/schematools/mongobiuser/options.go:38 +0xb8
main.main()
/home/vagrant/rpmbuild/BUILD/biconnector/schematools/mongobiuser/main/mongobiuser.go:15 +0x47
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1721 +0x1
######
How can I see all the users that are created?
The connector itself works quite fine...
Thansk!
Hi Bernd,
Did you try the below command?
mongobischema list biuser
sorry, please ignore the above comment.
whats the python version you have? # Packages : sudo rpm -qa | grep -E 'mongo|python'
The "panic: runtime error: index out of range" might be due to special characters.
can you post how did you create the mongobiuser? with exact syntax please..
Hi Raj,
its:
mongodb-bi-devel-1.1.3-1.el7.centos.x86_64
mongodb-bi-schematools-1.1.3-1.el7.centos.x86_64
libxml2-python-2.9.1-6.el7_2.3.x86_64
python-2.7.5-34.el7.x86_64
python-iniparse-0.4-9.el7.noarch
python-decorator-3.4.0-3.el7.noarch
python-lxml-3.2.1-4.el7.x86_64
python-javapackages-3.4.1-11.el7.noarch
python-chardet-2.2.1-1.el7_1.noarch
python-slip-0.4.0-2.el7.noarch
python-pyudev-0.15-7.el7_2.1.noarch
python-ethtool-0.8-5.el7.x86_64
rpm-python-4.11.3-17.el7.x86_64
mongodb-bi-1.1.3-1.el7.centos.x86_64
mongodb-bi-server-1.1.3-1.el7.centos.x86_64
mongodb-bi-contrib-1.1.3-1.el7.centos.x86_64
mongodb-bi-pymongo-1.1.3-1.x86_64
python-libs-2.7.5-34.el7.x86_64
python-dateutil-1.5-7.el7.noarch
python-gudev-147.2-7.el7.x86_64
python-dmidecode-3.10.13-11.el7.x86_64
python-kitchen-1.1.1-5.el7.noarch
libselinux-python-2.2.2-6.el7.x86_64
python-slip-dbus-0.4.0-2.el7.noarch
python-configobj-4.7.2-7.el7.noarch
python-urlgrabber-3.10-7.el7.noarch
python-rhsm-1.15.4-5.el7.x86_64
python-perf-3.10.0-327.10.1.el7.x86_64
mongodb-bi-libs-1.1.3-1.el7.centos.x86_64
mongodb-bi-multicorn-1.1.3-1.el7.centos.x86_64
mongodb-bi-fdw-1.1.3-1.noarch
python-hwdata-1.7.3-4.el7.noarch
ganglia-gmond-modules-python-3.7.1-1.x86_64
dbus-python-1.1.1-9.el7.x86_64
newt-python-0.52.15-4.el7.x86_64
python-pycurl-7.19.0-17.el7.x86_64
redhat-support-lib-python-0.9.7-3.el7.noarch
I have tried to create several users.. none of them has a special character...
its more or less:
mongobiuser create p_biuser1 'mongodb://user:password@server1:3000,server2:3000,server3:3000/schema?replicaSet=hostname&ssl=true&ssl_ca_certs=certfile.crt'
any idea?
Tanks a lot!
Post a Comment