73 lines
3.1 KiB
Python
73 lines
3.1 KiB
Python
"""Test hook for running the $operationMetrics stage in the background.
|
|
|
|
This hook runs continuously, but the run_aggregate_metrics_background.js file it runs will
|
|
internally sleep for 1 second between runs.
|
|
"""
|
|
|
|
import pymongo
|
|
import random
|
|
|
|
from buildscripts.resmokelib.testing.hooks.bghook import BGHook
|
|
|
|
|
|
class AggregateResourceConsumptionMetricsInBackground(BGHook):
|
|
"""A hook to run $operationMetrics stage in the background."""
|
|
|
|
def __init__(self, hook_logger, fixture, shell_options=None):
|
|
"""Initialize AggregateResourceConsumptionMetricsInBackground."""
|
|
|
|
description = "Run background $operationMetrics on all mongods while a test is running"
|
|
super().__init__(hook_logger, fixture, description, tests_per_cycle=None,
|
|
loop_delay_ms=1000)
|
|
|
|
def run_action(self):
|
|
"""Collects $operationMetrics on all non-arbiter nodes in the fixture."""
|
|
for node_info in self.fixture.get_node_info():
|
|
conn = pymongo.MongoClient(port=node_info.port)
|
|
# Filter out arbiters.
|
|
if "arbiterOnly" in conn.admin.command({"isMaster": 1}):
|
|
self.logger.info(
|
|
"Skipping background aggregation against test node: %s because it is an " +
|
|
"arbiter and has no data.", node_info.full_name)
|
|
return
|
|
|
|
# Clear the metrics about 10% of the time.
|
|
clear_metrics = random.random() < 0.1
|
|
self.logger.info("Running $operationMetrics with {clearMetrics: %s} on host: %s",
|
|
clear_metrics, node_info.full_name)
|
|
with conn.admin.aggregate(
|
|
[{"$operationMetrics": {"clearMetrics": clear_metrics}}]) as cursor:
|
|
for doc in cursor:
|
|
try:
|
|
self.verify_metrics(doc)
|
|
except:
|
|
self.logger.info(
|
|
"caught exception while verifying that all expected fields are in the" +
|
|
" metrics output: ", doc)
|
|
raise
|
|
|
|
def verify_metrics(self, doc):
|
|
"""Checks whether the output from $operatiomMetrics has the schema we expect."""
|
|
|
|
top_level_fields = [
|
|
"docBytesWritten", "docUnitsWritten", "idxEntryBytesWritten", "idxEntryUnitsWritten",
|
|
"totalUnitsWritten", "cpuNanos", "db", "primaryMetrics", "secondaryMetrics"
|
|
]
|
|
read_fields = [
|
|
"docBytesRead", "docUnitsRead", "idxEntryBytesRead", "idxEntryUnitsRead", "keysSorted",
|
|
"docUnitsReturned"
|
|
]
|
|
|
|
for key in top_level_fields:
|
|
assert key in doc, ("The metrics output is missing the property: " + key)
|
|
|
|
primary_metrics = doc["primaryMetrics"]
|
|
for key in read_fields:
|
|
assert key in primary_metrics, (
|
|
"The metrics output is missing the property: primaryMetrics." + key)
|
|
|
|
secondary_metrics = doc["secondaryMetrics"]
|
|
for key in read_fields:
|
|
assert key in secondary_metrics, (
|
|
"The metrics output is missing the property: secondaryMetrics." + key)
|