Design Note

Because the metric CPU Usage Per Sec returns usage across all CPUs in centiseconds (that is, 1/100 second), dividing by the CPU count yields per-core utilization (0.00–1.00 range, often rendered as a percentage with two decimal places).

CREATE OR REPLACE FUNCTION get_rh_chart_data_json RETURN CLOB IS
  l_json CLOB;
BEGIN
  WITH chart_data AS (
    SELECT TO_CHAR(m.end_time, 'HH24:MI') AS sample_time,
           ROUND((m.value / 100) / get_cpu_count(), 2) AS cpu_utilization_pct
      FROM v$metric_history m
     WHERE m.metric_name = 'CPU Usage Per Sec'
  )
  SELECT JSON_OBJECT(
            'type' VALUE 'line',
            'items' VALUE JSON_ARRAYAGG(
              JSON_OBJECT(
                'name' VALUE cd.sample_time,
                'series' VALUE 'CPU',
                'value' VALUE cd.cpu_utilization_pct
              ) ORDER BY cd.sample_time
            ),
            'renderTooltips' VALUE 'true',
            'valueFormat' VALUE 'PC',
            'renderXAxisLabels' VALUE 'true',
            'renderYAxisLabels' VALUE 'true',
            'xAxisTitle' VALUE 'Time (hours and minutes)',
            'yAxisTitle' VALUE 'CPU Utilization (%)'
          )
     INTO l_json
     FROM chart_data cd;

  RETURN l_json;
END;
/