diff --git a/collect.zpool.iostat.py b/collect.zpool.iostat.py index d66bed4..27512b1 100755 --- a/collect.zpool.iostat.py +++ b/collect.zpool.iostat.py @@ -2,7 +2,6 @@ import subprocess import csv import os import time -import re import argparse # Configuration parameters @@ -17,7 +16,6 @@ OUTPUT_FILE = "/root/zpool_iostat.csv" def update_csv_file(output_file, data): """ Writes data to a CSV file and rotates the file if necessary. - Parameters: output_file (str): Path to the CSV file where data will be written. data (list): The data to be written to the file. @@ -27,11 +25,9 @@ def update_csv_file(output_file, data): with open(output_file, "w", newline="") as csv_file: fieldnames = data[0].keys() if data else [] csv_writer = csv.DictWriter(csv_file, fieldnames=fieldnames) - csv_writer.writeheader() for row in data: csv_writer.writerow(row) - print(f"Data successfully written to {output_file}") rotate_file_if_needed(output_file) except Exception as e: @@ -41,7 +37,6 @@ def update_csv_file(output_file, data): def rotate_file_if_needed(file_path): """ Rotates the file if it exceeds a specified size. The existing file is renamed to '.old'. - Parameters: file_path (str): Path to the file that should be rotated. """ @@ -61,10 +56,8 @@ def rotate_file_if_needed(file_path): def load_existing_data(file_path): """ Loads existing data from a CSV file. - Parameters: file_path (str): Path to the CSV file. - Returns: list: The data loaded from the file, or an empty list if the file doesn't exist or an error occurs. """ @@ -86,10 +79,8 @@ def load_existing_data(file_path): def remove_k(value_with_unit): """ Removes the 'K' unit from a value, if present, from the IOPS section. - Parameters: value_with_unit (str): The string containing the value and possibly a 'K' unit. - Returns: float: The numerical value, with 'K' removed if it was present. """ @@ -102,24 +93,20 @@ def remove_k(value_with_unit): def convert_to_mib(value_with_unit): """ Converts a value with a unit (K, M, G, T) to MiB. - Parameters: value_with_unit (str): The string containing the value and unit. - Returns: float: The value converted to MiB, or 0 if the input is invalid. """ # Check if the string is valid if not value_with_unit or not value_with_unit[-1].isalpha(): return 0.0 - # Extract the unit and value unit = value_with_unit[-1].upper() # Ensure unit is uppercase for consistency try: value = float(value_with_unit[:-1]) except ValueError: return 0.0 - # Convert based on the unit if unit == "K": return round(value / 1024.0, 1) # Convert KiB to MiB @@ -138,40 +125,32 @@ def convert_time_to_ms(value_with_unit): """ Converts a time value with a unit (ms, us, ns) to milliseconds (ms), rounded to three decimal places. Returns 0 if the input is '-', indicating no data. - Parameters: value_with_unit (str): The string containing the value and unit. - Returns: float: The value converted to milliseconds (ms), rounded to three decimal places, or 0 if the input is invalid or '-'. """ if value_with_unit == "-": # Handle no data case return 0 - try: # Strip and lower case to normalize value_with_unit = value_with_unit.strip().lower() - # Check for nanoseconds if value_with_unit.endswith("ns"): value = float(value_with_unit[:-2]) return round(value / 1e6, 1) # Convert ns to ms and round - # Check for microseconds elif value_with_unit.endswith("us"): value = float(value_with_unit[:-2]) return round(value / 1000.0, 1) # Convert us to ms and round - # Check for milliseconds elif value_with_unit.endswith("ms"): value = float(value_with_unit[:-2]) return round(value, 3) # Already in ms and round - # If no known unit, assume it's in milliseconds and round else: return round(float(value_with_unit), 1) - except ValueError: # Log the error if conversion fails print(f"Warning: Unrecognized or malformed time value '{value_with_unit}'.") @@ -182,27 +161,22 @@ def parse_iostat_output(output): """ Parses the output of the `zpool iostat` command to include pool, vdev, disk level data, and does not specifically skip the 'logs' line. - Parameters: output (str): The output string from the `zpool iostat` command. - Returns: list: A list of dictionaries, each representing an entity (pool, vdev, or disk) and its metrics. """ parsed_data = [] lines = output.strip().split("\n") data_started = False - for line in lines: if "capacity" in line and "operations" in line and "bandwidth" in line: # This line indicates the end of the headers and the start of relevant data. data_started = True continue # Skip the header line itself - if data_started and "-----" in line or line.startswith("pool"): # Skip separator lines and the column headers repeated in the output. continue - if data_started: # Process lines containing pool, vdev, and disk level data. fields = line.split() @@ -216,7 +190,6 @@ def parse_iostat_output(output): ): # Skip lines that do not contain numeric data where expected. continue - data_entry = { "time": time.strftime("%Y-%m-%dT%H:%M:%SZ"), "name": fields[0], @@ -263,7 +236,6 @@ def parse_iostat_output(output): parsed_data.append(data_entry) except Exception as e: print(f"Error processing line: '{line}' - {e}") - return parsed_data