def _build_equation_stat_inputs(eq_stat_names):
    input_stats = []
    for stat_name in eq_stat_names:
        stat_name, fields = _parse_fields(stat_name)
        input_stats.append(DerivedStatInput(stat_name, fields))

    return input_stats
def _parse_composite_stats(composite_stats_cfg):
    # Example of what is expected for each stat_cfg:
    # sum(node.ifs.ops.in[:field1:field2])
    composite_stats = []
    for stat_cfg in composite_stats_cfg.split():
        bracket1 = stat_cfg.find("(")
        bracket2 = stat_cfg.find(")")
        if bracket1 <= 0 or bracket2 == -1 or bracket1 > bracket2:
            raise RuntimeError("Failed to parse operation from %s."
                               "Expected: op(stat) where op is avg, min, max, "
                               " or sum and stat is the name of a base OneFS "
                               ' statistic name that starts with "node.".' %
                               stat_cfg)
        op_name = stat_cfg[0:bracket1]
        if op_name not in COMPOSITE_OPERATIONS:
            raise RuntimeError("Invalid operation %s specified for %s." %
                               (op_name, stat_cfg))

        in_stat_name = stat_cfg[bracket1 + 1:bracket2]
        if in_stat_name.startswith("node.") is False:
            raise RuntimeError("Invalid stat name %s specified for %s."
                               ' Composite stats must start with "node.".' %
                               (op_name, stat_cfg))
        out_stat_name = "cluster.%s.%s" % (in_stat_name.replace(":",
                                                                "."), op_name)
        in_stat_name, fields = _parse_fields(in_stat_name)
        # TODO should validate that this is a valid stat name
        composite_stat = ClusterCompositeStatComputer(
            DerivedStatInput(in_stat_name, fields),
            out_stat_name,
            COMPOSITE_OPERATIONS[op_name],
        )
        composite_stats.append(composite_stat)

    return composite_stats
def _parse_pct_change_stats(pct_change_stats_cfg):
    # Expected is just a white-space delimitted list of stat names
    pct_change_stats = []
    for stat_name in pct_change_stats_cfg.split():
        out_stat_name = stat_name.replace(":", ".") + ".percentchange"
        stat_name, fields = _parse_fields(stat_name)
        pct_change_stats.append(
            PercentChangeStatComputer(DerivedStatInput(stat_name, fields),
                                      out_stat_name))
    return pct_change_stats