]> www.infradead.org Git - users/hch/misc.git/commitdiff
perf python: Add metrics function
authorIan Rogers <irogers@google.com>
Tue, 19 Aug 2025 01:39:39 +0000 (18:39 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 3 Sep 2025 15:34:54 +0000 (12:34 -0300)
The metrics function returns a list dictionaries describing metrics as
strings mapping to strings, except for metric groups that are a string
mapping to a list of strings. For example:
```
>>> import perf
>>> perf.metrics()[0]
{'MetricGroup': ['Power'], 'MetricName': 'C10_Pkg_Residency',
 'PMU': 'default_core', 'MetricExpr': 'cstate_pkg@c10\\-residency@ / TSC',
 'ScaleUnit': '100%', 'BriefDescription': 'C10 residency percent per package'}
```

Reviewed-by: Howard Chu <howardchu95@gmail.com>
Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Chun-Tse Shao <ctshao@google.com>
Cc: Collin Funk <collin.funk1@gmail.com>
Cc: Dr. David Alan Gilbert <linux@treblig.org>
Cc: Gautam Menghani <gautam@linux.ibm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Falcon <thomas.falcon@intel.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Xu Yang <xu.yang_2@nxp.com>
Link: https://lore.kernel.org/r/20250819013941.209033-10-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/python.c

index ad8a5446ae482e81da81e39e3b43b027124e8d44..47178404802f4069c76e546e27c5d932d35aa1cd 100644 (file)
@@ -2083,7 +2083,93 @@ static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args)
        return result;
 }
 
+static PyObject *pyrf__metrics_groups(const struct pmu_metric *pm)
+{
+       PyObject *groups = PyList_New(/*len=*/0);
+       const char *mg = pm->metric_group;
+
+       if (!groups)
+               return NULL;
+
+       while (mg) {
+               PyObject *val = NULL;
+               const char *sep = strchr(mg, ';');
+               size_t len = sep ? (size_t)(sep - mg) : strlen(mg);
+
+               if (len > 0) {
+                       val = PyUnicode_FromStringAndSize(mg, len);
+                       if (val)
+                               PyList_Append(groups, val);
+
+                       Py_XDECREF(val);
+               }
+               mg = sep ? sep + 1 : NULL;
+       }
+       return groups;
+}
+
+static int pyrf__metrics_cb(const struct pmu_metric *pm,
+                           const struct pmu_metrics_table *table __maybe_unused,
+                           void *vdata)
+{
+       PyObject *py_list = vdata;
+       PyObject *dict = PyDict_New();
+       PyObject *key = dict ? PyUnicode_FromString("MetricGroup") : NULL;
+       PyObject *value = key ? pyrf__metrics_groups(pm) : NULL;
+
+       if (!value || PyDict_SetItem(dict, key, value) != 0) {
+               Py_XDECREF(key);
+               Py_XDECREF(value);
+               Py_XDECREF(dict);
+               return -ENOMEM;
+       }
+
+       if (!add_to_dict(dict, "MetricName", pm->metric_name) ||
+           !add_to_dict(dict, "PMU", pm->pmu) ||
+           !add_to_dict(dict, "MetricExpr", pm->metric_expr) ||
+           !add_to_dict(dict, "MetricThreshold", pm->metric_threshold) ||
+           !add_to_dict(dict, "ScaleUnit", pm->unit) ||
+           !add_to_dict(dict, "Compat", pm->compat) ||
+           !add_to_dict(dict, "BriefDescription", pm->desc) ||
+           !add_to_dict(dict, "PublicDescription", pm->long_desc) ||
+           PyList_Append(py_list, dict) != 0) {
+               Py_DECREF(dict);
+               return -ENOMEM;
+       }
+       Py_DECREF(dict);
+       return 0;
+}
+
+static PyObject *pyrf__metrics(PyObject *self, PyObject *args)
+{
+       const struct pmu_metrics_table *table = pmu_metrics_table__find();
+       PyObject *list = PyList_New(/*len=*/0);
+       int ret;
+
+       if (!list)
+               return NULL;
+
+       ret = pmu_metrics_table__for_each_metric(table, pyrf__metrics_cb, list);
+       if (!ret)
+               ret = pmu_for_each_sys_metric(pyrf__metrics_cb, list);
+
+       if (ret) {
+               Py_DECREF(list);
+               errno = -ret;
+               PyErr_SetFromErrno(PyExc_OSError);
+               return NULL;
+       }
+       return list;
+}
+
 static PyMethodDef perf__methods[] = {
+       {
+               .ml_name  = "metrics",
+               .ml_meth  = (PyCFunction) pyrf__metrics,
+               .ml_flags = METH_NOARGS,
+               .ml_doc   = PyDoc_STR(
+                       "Returns a list of metrics represented as string values in dictionaries.")
+       },
        {
                .ml_name  = "tracepoint",
                .ml_meth  = (PyCFunction) pyrf__tracepoint,