diff options
author | Austin S. Hemmelgarn <austin@netdata.cloud> | 2020-01-24 10:04:27 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-24 10:04:27 -0500 |
commit | db265d6f63182cd5ee58bf6f76cb50a5f41dd263 (patch) | |
tree | 701ae3611ae122c6cd54f5febc981c3254f89c77 /daemon | |
parent | d1eafad8b02fdef2f4ddcbfa6c35ec5594b248b3 (diff) |
Improve the system-info.sh script to report CPU and RAM meta-data. (#7815)
* Add CPU information collection for Linux and FreeBSD.
This adds logic to system.info.sh to collect info about the system's CPU.
It adds the following keys to the output of the script:
* NETDATA_CPU_LOGICAL_CPU_COUNT: This reports the number of logical CPU
cores the system is actually using (including offline ones). This may
differ from the CPU's advertised core count, but is what most people
actually care about.
* NETDATA_CPU_VENDOR: This reports the CPU manufacturer. This is needed
because some systems do not include the manufacturer name in the CPU
model name.
* NETDATA_CPU_MODEL: This reports the CPU model. It may or may not
include any of a model number, intended operating frequency, and
manufacturer name.
* NETDATA_CPU_FREQ: This reports a best guess at the design frequency
for the CPU. It may instead be the max boost frequency. This is
reported as a number with associated units, which will usually be
either hertz or megahertz.
* NETDATA_CPU_DETECTION: This reports the method used to detect the CPU
information, It will be either 'none' if no detection was successful,
or a space-separated list of detection methods.
This may potentially use any of the following detection methods:
* lscpu: Uses a mix of information from across the system. Requires the
`lscpu` command to be installed.
* dmidecode: Uses the information from the DMI tables. Requires hardware
support as well as the `dmidecode` command.
* nproc: Uses the `nproc` command from the GNU coreutils to get a count
of logical processors.
* sysctl: Uses the `sysctl` command on FreeBSD to fetch information.
* sysfs: Uses /sys on Linux to fetch information.
* procfs: Uses /proc/cpuinfo on Linux to fetch information.
* uname: Uses the `uname` command from the GNU coreutils to get CPU
model and vendor information.
All values tht were not successfully detected should read back as
'unknown'. Some values may have spaces present, and thus are quoted in
the output.
* Collect total system RAM info in system-info.sh
This collects info about the total usable system RAM in the system-info.sh
script.
It adds the following two keys to the output of the script:
* NETDATA_TOTAL_RAM: Reports the total usable system RAM as a number
with an associated unit, usually as bytes or kilobytes. Reports
'unknown' if this couldn't be determined.
* NETDATA_RAM_DETECTION: Indicates how we detected the total RAM, or
'none' if we couldn't figure out the total RAM.
* Make lscpu output parsing more robust.
* Remove extra quotes.
The output is not parsed as shell variables, but using a special parser
that just reads everything from the `=` to EOL as the value.
* Coerce output to base units.
This properly converts the output for CPU frequencies and RAM sizes to
use base units of Hertz or bytes, allowing for simpler parsing of the
output.
* Fix incorrect number handling in total RAM parsing.
* Correctly fix incorrect number handling in total RAM parsing.
* Fix parsing of `lscpu` output.
This properly recognizes the CPU frequency value as MHz and truncates
the value to an integer.
Diffstat (limited to 'daemon')
-rwxr-xr-x | daemon/system-info.sh | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/daemon/system-info.sh b/daemon/system-info.sh index cd3fc6ee97..3ffb3863aa 100755 --- a/daemon/system-info.sh +++ b/daemon/system-info.sh @@ -169,6 +169,123 @@ else fi fi +# ------------------------------------------------------------------------------------------------- +# Detect information about the CPU + +LCPU_COUNT="unknown" +CPU_MODEL="unknown" +CPU_VENDOR="unknown" +CPU_FREQ="unknown" +CPU_INFO_SOURCE="none" + +possible_cpu_freq="" +nproc="$(command -v nproc)" +lscpu="$(command -v lscpu)" +lscpu_output="" +dmidecode="$(command -v dmidecode)" +dmidecode_output="" + +if [ -n "${lscpu}" ] && lscpu >/dev/null 2>&1 ; then + lscpu_output="$(LC_NUMERIC=C ${lscpu} 2>/dev/null)" + CPU_INFO_SOURCE="lscpu" + LCPU_COUNT="$(echo "${lscpu_output}" | grep "^CPU(s):" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + CPU_VENDOR="$(echo "${lscpu_output}" | grep "^Vendor ID:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + CPU_MODEL="$(echo "${lscpu_output}" | grep "^Model name:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + possible_cpu_freq="$(echo "${lscpu_output}" | grep -F "CPU max MHz:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | grep -o '^[0-9]*') MHz" +elif [ -n "${dmidecode}" ] && dmidecode -t processor >/dev/null 2>&1 ; then + dmidecode_output="$(${dmidecode} -t processor 2>/dev/null)" + CPU_INFO_SOURCE="dmidecode" + LCPU_COUNT="$(echo "${dmidecode_output}" | grep -F "Thread Count:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + CPU_VENDOR="$(echo "${dmidecode_output}" | grep -F "Manufacturer:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + CPU_MODEL="$(echo "${dmidecode_output}" | grep -F "Version:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + possible_cpu_freq="$(echo "${dmidecode_output}" | grep -F "Current Speed:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" +else + if [ -n "${nproc}" ] ; then + CPU_INFO_SOURCE="nproc" + LCPU_COUNT="$(${nproc})" + elif [ "${KERNEL_NAME}" = FreeBSD ] ; then + CPU_INFO_SOURCE="sysctl" + LCPU_COUNT="$(sysctl -n kern.smp.cpus)" + elif [ -d /sys/devices/system/cpu ] ; then + CPU_INFO_SOURCE="sysfs" + # This is potentially more accurate than checking `/proc/cpuinfo`. + LCPU_COUNT="$(find /sys/devices/system/cpu -mindepth 1 -maxdepth 1 -type d -name 'cpu*' | grep -cEv 'idle|freq')" + elif [ -r /proc/cpuinfo ] ; then + CPU_INFO_SOURCE="procfs" + LCPU_COUNT="$(grep -c ^processor /proc/cpuinfo)" + fi + + # If we have GNU uname, we can use that to get CPU info (probably). + if unmae --version 2>/dev/null | grep -qF 'GNU coreutils' ; then + CPU_INFO_SOURCE="${CPU_INFO_SOURCE} uname" + CPU_MODEL="$(uname -p)" + CPU_VENDOR="$(uname -i)" + elif [ "${KERNEL_NAME}" = FreeBSD ] ; then + if ( echo "${CPU_INFO_SOURCE}" | grep -qv sysctl ) ; then + CPU_INFO_SOURCE="${CPU_INFO_SOURCE} sysctl" + fi + + CPU_MODEL="$(sysctl -n hw.model)" + elif [ -r /proc/cpuinfo ] ; then + if ( echo "${CPU_INFO_SOURCE}" | grep -qv procfs ) ; then + CPU_INFO_SOURCE="${CPU_INFO_SOURCE} procfs" + fi + + CPU_MODEL="$(grep -F "model name" /proc/cpuinfo | head -n 1 | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + CPU_VENDOR="$(grep -F "vendor_id" /proc/cpuinfo | head -n 1 | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + fi +fi + +if [ -r /sys/devices/system/cpu/cpu0/cpufreq/base_frequency ] ; then + if ( echo "${CPU_INFO_SOURCE}" | grep -qv sysfs ) ; then + CPU_INFO_SOURCE="${CPU_INFO_SOURCE} sysfs" + fi + + CPU_FREQ="$(cat /sys/devices/system/cpu/cpu0/cpufreq/base_frequency)" +elif [ -n "${possible_cpu_freq}" ] ; then + CPU_FREQ="${possible_cpu_freq}" +elif [ -r /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq ] ; then + if ( echo "${CPU_INFO_SOURCE}" | grep -qv sysfs ) ; then + CPU_INFO_SOURCE="${CPU_INFO_SOURCE} sysfs" + fi + + CPU_FREQ="$(cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq)" +fi + +freq_units="$(echo "${CPU_FREQ}" | cut -f 2 -d ' ')" + +case "${freq_units}" in + GHz) + value="$(echo "${CPU_FREQ}" | cut -f 1 -d ' ')" + CPU_FREQ="$((value*1000*1000*1000))" + ;; + MHz) + value="$(echo "${CPU_FREQ}" | cut -f 1 -d ' ')" + CPU_FREQ="$((value*1000*1000))" + ;; + KHz) + value="$(echo "${CPU_FREQ}" | cut -f 1 -d ' ')" + CPU_FREQ="$((value*1000))" + ;; + *) + ;; +esac + +# ------------------------------------------------------------------------------------------------- +# Detect the total system RAM + +TOTAL_RAM="unknown" +RAM_DETECTION="none" + +if [ "${KERNEL_NAME}" = FreeBSD ] ; then + RAM_DETECTION="sysctl" + TOTAL_RAM="$(sysctl -n hw.physmem)" +elif [ -r /proc/meminfo ] ; then + RAM_DETECTION="procfs" + TOTAL_RAM="$(grep -F MemTotal /proc/meminfo | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | cut -f 1 -d ' ')" + TOTAL_RAM="$((TOTAL_RAM*1024))" +fi + echo "NETDATA_CONTAINER_OS_NAME=${CONTAINER_NAME}" echo "NETDATA_CONTAINER_OS_ID=${CONTAINER_ID}" @@ -189,4 +306,11 @@ echo "NETDATA_SYSTEM_VIRTUALIZATION=${VIRTUALIZATION}" echo "NETDATA_SYSTEM_VIRT_DETECTION=${VIRT_DETECTION}" echo "NETDATA_SYSTEM_CONTAINER=${CONTAINER}" echo "NETDATA_SYSTEM_CONTAINER_DETECTION=${CONT_DETECTION}" +echo "NETDATA_CPU_LOGICAL_CPU_COUNT=${LCPU_COUNT}" +echo "NETDATA_CPU_VENDOR=${CPU_VENDOR}" +echo "NETDATA_CPU_MODEL=${CPU_MODEL}" +echo "NETDATA_CPU_FREQ=${CPU_FREQ}" +echo "NETDATA_CPU_DETECTION=${CPU_INFO_SOURCE}" +echo "NETDATA_TOTAL_RAM=${TOTAL_RAM}" +echo "NETDATA_RAM_DETECTION=${RAM_DETECTION}" |