├── .github
└── workflows
│ ├── build-image.yml
│ └── update-description.yml
├── .gitignore
├── .rspec
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── README.md
├── app
├── application.rb
├── exporter.rb
├── n_vidia_smi.rb
└── n_vidia_smi_xml.rb
└── spec
├── fixtures
├── nvidia-smi-1.csv
├── nvidia-smi-2.csv
├── nvidia-smi-3.xml
├── nvidia-smi-4.xml
├── parsed-1.json
└── parsed-2.json
├── helpers
└── fixture.rb
├── n_vidia_smi_spec.rb
├── n_vidia_smi_xml_spec.rb
└── spec_helper.rb
/.github/workflows/build-image.yml:
--------------------------------------------------------------------------------
1 | name: Docker image
2 | on:
3 | release:
4 | types: [published]
5 | jobs:
6 | build:
7 | name: rspec
8 | runs-on: ubuntu-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v1
12 | - uses: actions/setup-ruby@v1
13 | with:
14 | ruby-version: 3.0.0
15 |
16 | - name: Run bundle install
17 | run: |
18 | gem install bundler
19 | bundle install --jobs 4 --retry 3
20 |
21 | - name: Build and test with rspec
22 | env:
23 | RAILS_ENV: test
24 | run: bundle exec rspec
25 |
26 | buildx:
27 | name: build and push image
28 | runs-on: ubuntu-latest
29 |
30 | steps:
31 | - name: Checkout
32 | uses: actions/checkout@v2
33 |
34 | - name: Variables
35 | id: variables
36 | run: |
37 | echo ::set-output name=SOURCE_NAME::${GITHUB_REF#refs/*/}
38 | echo ::set-output name=SOURCE_BRANCH::${GITHUB_REF#refs/heads/}
39 | echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/}
40 | echo ::set-output name=REPOSITORY_NAME::$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}')
41 | echo ::set-output name=FULL_VERSION::$(git describe --tags --dirty --always)
42 | echo ::set-output name=TARGET_PLATFORMS::"linux/amd64"
43 | - name: Set up Docker Buildx
44 | id: buildx
45 | uses: crazy-max/ghaction-docker-buildx@v3
46 | with:
47 | buildx-version: latest
48 | qemu-version: latest
49 |
50 | - name: Available platforms
51 | run: echo ${{ steps.buildx.outputs.platforms }}
52 |
53 | - name: Login to DockerHub
54 | run: echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin
55 |
56 | - name: Build and push tag
57 | run: |
58 | docker buildx build \
59 | --platform ${{ steps.variables.outputs.TARGET_PLATFORMS }} \
60 | --build-arg FULL_VERSION=${{ steps.variables.outputs.FULL_VERSION }} \
61 | -t a00s/${{ steps.variables.outputs.REPOSITORY_NAME }}:${{ steps.variables.outputs.SOURCE_TAG }} \
62 | . \
63 | --push
64 | - name: Build and push latest
65 | run: |
66 | docker buildx build \
67 | --platform ${{ steps.variables.outputs.TARGET_PLATFORMS }} \
68 | --build-arg FULL_VERSION=${{ steps.variables.outputs.FULL_VERSION }} \
69 | -t a00s/${{ steps.variables.outputs.REPOSITORY_NAME }}:latest \
70 | . \
71 | --push
72 |
--------------------------------------------------------------------------------
/.github/workflows/update-description.yml:
--------------------------------------------------------------------------------
1 | name: Update Docker Hub Description
2 | on:
3 | push:
4 | branches:
5 | - master
6 | paths:
7 | - README.md
8 | - .github/workflows/update-description.yml
9 | jobs:
10 | dockerHubDescription:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Variables
14 | id: variables
15 | run: |
16 | echo ::set-output name=SOURCE_NAME::${GITHUB_REF#refs/*/}
17 | echo ::set-output name=SOURCE_BRANCH::${GITHUB_REF#refs/heads/}
18 | echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/}
19 | echo ::set-output name=REPOSITORY_NAME::$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}')
20 | - name: Checkout
21 | uses: actions/checkout@v2
22 |
23 | - name: Docker Hub Description
24 | uses: peter-evans/dockerhub-description@v2
25 | env:
26 | DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
27 | DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
28 | DOCKERHUB_REPOSITORY: a00s/${{ steps.variables.outputs.REPOSITORY_NAME }}
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .ruby-*
2 | .envrc
3 | .idea/
4 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --require spec_helper
2 | --no-profile
3 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ruby:3.0.0-buster
2 |
3 | ENV LANG C.UTF-8
4 | ENV DEBIAN_FRONTEND noninteractive
5 |
6 | ARG NVIDIA_PUB_KEY="https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub"
7 | ARG NVIDIA_REPO="deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64 /"
8 | ARG NVIDIA_VERSION="460.32.03-0ubuntu1"
9 |
10 | WORKDIR /app
11 | COPY . /app
12 |
13 | RUN \
14 | apt-get update \
15 | && apt-get install -y --no-install-recommends build-essential wget \
16 | && wget -qO - ${NVIDIA_PUB_KEY} | apt-key add - \
17 | && echo ${NVIDIA_REPO} > /etc/apt/sources.list.d/cuda.list \
18 | && apt-get update \
19 | && apt-get install -y --no-install-recommends libnvidia-compute-460=${NVIDIA_VERSION} nvidia-utils-460=${NVIDIA_VERSION} \
20 | && rm -rf /var/lib/apt/lists/* \
21 | && bundle install --deployment --without test
22 |
23 | CMD ["bundle", "exec", "ruby", "app/application.rb", "1>&2"]
24 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'sinatra'
4 | gem 'puma'
5 | gem 'activesupport'
6 | gem 'nokogiri'
7 |
8 | group :test do
9 | gem 'rspec'
10 | end
11 |
12 | group :development do
13 | gem 'pry'
14 | end
15 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | activesupport (6.1.3)
5 | concurrent-ruby (~> 1.0, >= 1.0.2)
6 | i18n (>= 1.6, < 2)
7 | minitest (>= 5.1)
8 | tzinfo (~> 2.0)
9 | zeitwerk (~> 2.3)
10 | coderay (1.1.3)
11 | concurrent-ruby (1.1.8)
12 | diff-lcs (1.4.4)
13 | i18n (1.8.9)
14 | concurrent-ruby (~> 1.0)
15 | method_source (1.0.0)
16 | mini_portile2 (2.8.0)
17 | minitest (5.14.4)
18 | mustermann (1.1.1)
19 | ruby2_keywords (~> 0.0.1)
20 | nio4r (2.5.8)
21 | nokogiri (1.13.6)
22 | mini_portile2 (~> 2.8.0)
23 | racc (~> 1.4)
24 | pry (0.14.0)
25 | coderay (~> 1.1)
26 | method_source (~> 1.0)
27 | puma (5.6.4)
28 | nio4r (~> 2.0)
29 | racc (1.6.0)
30 | rack (2.2.3.1)
31 | rack-protection (2.2.0)
32 | rack
33 | rspec (3.10.0)
34 | rspec-core (~> 3.10.0)
35 | rspec-expectations (~> 3.10.0)
36 | rspec-mocks (~> 3.10.0)
37 | rspec-core (3.10.1)
38 | rspec-support (~> 3.10.0)
39 | rspec-expectations (3.10.1)
40 | diff-lcs (>= 1.2.0, < 2.0)
41 | rspec-support (~> 3.10.0)
42 | rspec-mocks (3.10.2)
43 | diff-lcs (>= 1.2.0, < 2.0)
44 | rspec-support (~> 3.10.0)
45 | rspec-support (3.10.2)
46 | ruby2_keywords (0.0.5)
47 | sinatra (2.2.0)
48 | mustermann (~> 1.0)
49 | rack (~> 2.2)
50 | rack-protection (= 2.2.0)
51 | tilt (~> 2.0)
52 | tilt (2.0.10)
53 | tzinfo (2.0.4)
54 | concurrent-ruby (~> 1.0)
55 | zeitwerk (2.4.2)
56 |
57 | PLATFORMS
58 | ruby
59 |
60 | DEPENDENCIES
61 | activesupport
62 | nokogiri
63 | pry
64 | puma
65 | rspec
66 | sinatra
67 |
68 | BUNDLED WITH
69 | 2.2.3
70 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Nvidia SMI Exporter
2 | ---------------------
3 | Another one nvidia-smi data exporter for Prometheus.
4 |
5 |
6 |
7 | ```bash
8 | > curl localhost:9454/ping
9 | OK
10 |
11 | > curl localhost:9454/metrics
12 | nvidia_smi_attached_gpus 2
13 | nvidia_smi_display_mode{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
14 | nvidia_smi_display_active{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
15 | nvidia_smi_persistence_mode{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
16 | nvidia_smi_accounting_mode{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
17 | nvidia_smi_accounting_mode_buffer_size{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 4000
18 | nvidia_smi_minor_number{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
19 | nvidia_smi_multigpu_board{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
20 | nvidia_smi_inforom_version_oem_object{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1.1
21 | nvidia_smi_pci_pci_sub_system_id{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 37021458
22 | nvidia_smi_pci_pci_gpu_link_info_pcie_gen_max_link_gen{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 3
23 | nvidia_smi_pci_pci_gpu_link_info_pcie_gen_current_link_gen{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 3
24 | nvidia_smi_pci_pci_gpu_link_info_link_widths_max_link_width{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 16
25 | nvidia_smi_pci_pci_gpu_link_info_link_widths_current_link_width{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
26 | nvidia_smi_pci_replay_counter{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 65535
27 | nvidia_smi_pci_replay_rollover_counter{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
28 | nvidia_smi_pci_tx_util_bytes_per_second{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 11264000
29 | nvidia_smi_pci_rx_util_bytes_per_second{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 31744000
30 | nvidia_smi_fan_speed_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0.53
31 | nvidia_smi_performance_state{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 2
32 | nvidia_smi_clocks_throttle_reasons_clocks_throttle_reason_gpu_idle{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
33 | nvidia_smi_clocks_throttle_reasons_clocks_throttle_reason_applications_clocks_setting{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
34 | nvidia_smi_clocks_throttle_reasons_clocks_throttle_reason_sw_power_cap{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
35 | nvidia_smi_clocks_throttle_reasons_clocks_throttle_reason_hw_slowdown{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
36 | nvidia_smi_clocks_throttle_reasons_clocks_throttle_reason_hw_thermal_slowdown{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
37 | nvidia_smi_clocks_throttle_reasons_clocks_throttle_reason_hw_power_brake_slowdown{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
38 | nvidia_smi_clocks_throttle_reasons_clocks_throttle_reason_sync_boost{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
39 | nvidia_smi_clocks_throttle_reasons_clocks_throttle_reason_sw_thermal_slowdown{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
40 | nvidia_smi_clocks_throttle_reasons_clocks_throttle_reason_display_clocks_setting{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
41 | nvidia_smi_fb_memory_usage_total_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 8510242816
42 | nvidia_smi_fb_memory_usage_used_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 3040870400
43 | nvidia_smi_fb_memory_usage_free_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 5469372416
44 | nvidia_smi_bar1_memory_usage_total_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 268435456
45 | nvidia_smi_bar1_memory_usage_used_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 5242880
46 | nvidia_smi_bar1_memory_usage_free_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 263192576
47 | nvidia_smi_compute_mode{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
48 | nvidia_smi_utilization_gpu_util_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1.0
49 | nvidia_smi_utilization_memory_util_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1.0
50 | nvidia_smi_utilization_encoder_util_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0.0
51 | nvidia_smi_utilization_decoder_util_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0.0
52 | nvidia_smi_encoder_stats_session_count{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
53 | nvidia_smi_encoder_stats_average_fps{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
54 | nvidia_smi_encoder_stats_average_latency{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
55 | nvidia_smi_fbc_stats_session_count{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
56 | nvidia_smi_fbc_stats_average_fps{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
57 | nvidia_smi_fbc_stats_average_latency{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
58 | nvidia_smi_temperature_gpu_temp_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 67.0
59 | nvidia_smi_temperature_gpu_temp_max_threshold_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 96.0
60 | nvidia_smi_temperature_gpu_temp_slow_threshold_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 93.0
61 | nvidia_smi_temperature_gpu_target_temperature_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 83.0
62 | nvidia_smi_supported_gpu_target_temp_gpu_target_temp_min_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 60.0
63 | nvidia_smi_supported_gpu_target_temp_gpu_target_temp_max_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 92.0
64 | nvidia_smi_power_readings_power_state{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 2
65 | nvidia_smi_power_readings_power_management{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
66 | nvidia_smi_power_readings_power_draw_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 211.86
67 | nvidia_smi_power_readings_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 216.0
68 | nvidia_smi_power_readings_default_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 200.0
69 | nvidia_smi_power_readings_enforced_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 216.0
70 | nvidia_smi_power_readings_min_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 100.0
71 | nvidia_smi_power_readings_max_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 216.0
72 | nvidia_smi_clocks_graphics_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1784000000.0
73 | nvidia_smi_clocks_sm_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1784000000.0
74 | nvidia_smi_clocks_mem_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 5514000000.0
75 | nvidia_smi_clocks_video_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1594000000.0
76 | nvidia_smi_max_clocks_graphics_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1999000000.0
77 | nvidia_smi_max_clocks_sm_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1999000000.0
78 | nvidia_smi_max_clocks_mem_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 5005000000.0
79 | nvidia_smi_max_clocks_video_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1708000000.0
80 | ```
81 |
82 | Caveats
83 | =======
84 |
85 | In XML mode (see below) the exporter skips all implicit arrays like this:
86 |
87 | ```xml
88 |
89 |
90 | 3504 MHz
91 | 1721 MHz <== will skip all supported_graphics_clock
92 | 1708 MHz
93 | 1695 MHz
94 | 1683 MHz
95 | 1670 MHz
96 | 1657 MHz
97 | 1645 MHz
98 | 1632 MHz
99 | ```
100 |
101 | Also, it skips all empty and "N/A" values (and their keys accordingly).
102 |
103 | Prometheus is [not supporting](https://github.com/prometheus/prometheus/issues/2227) string values, thus exporter converts some strings to numbers:
104 | - `Disabled`, `Not Active`, `No`, `Not Supported` and `Unsupported` will convert to 0
105 | - `Enabled`, `Active`, `Yes`, `Supported` will convert to 1
106 | - `P0`..`P15` will convert to 0..15
107 | - `1x`, `2x`, `4x`, `8x`, `16x`, `32x` (pci lines) will convert to 1,2,4,8,16,32
108 | - `Default`, `Exclusive_Thread`, `Prohibited`, `Exclusive_Process` (_compute_mode) will convert to 0..3
109 |
110 | Other not integer/float strings will eliminate.
111 |
112 | Run in Docker
113 | =============
114 |
115 | `nvidia-smi` requires using the same versions of packages (`libnvidia-compute-460` and `nvidia-utils-460`) inside the container and outside (on the host).
116 |
117 | 1) Get driver version on the host:
118 |
119 | ```shell
120 | > dpkg --list | grep nvidia-driver-460
121 | ii nvidia-driver-460 460.27.04-0ubuntu1 amd64 NVIDIA driver metapackage
122 | ```
123 |
124 | 2) Build container with appropriate version of driver:
125 |
126 | ```shell
127 | > docker build . --tag nvidia-smi-exporter --build-arg NVIDIA_VERSION=460.27.04-0ubuntu1
128 | ```
129 |
130 | All available versions can be found [in the Cuda repository](https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/)
131 |
132 | 3) Run with `--privileged` flag (not recommended due to security)
133 | ```shell
134 | > docker run --rm --privileged -p 9454:9454 nvidia-smi-exporter
135 | ```
136 |
137 | or enumerating (map inside container) all devices explicitly
138 |
139 | ```shell
140 | > docker run --rm \
141 | --device /dev/nvidiactl:/dev/nvidiactl \
142 | --device /dev/nvidia0:/dev/nvidia0 \
143 | --device /dev/nvidia1:/dev/nvidia1 \
144 | -p 9454:9454 nvidia-smi-exporter
145 | ```
146 |
147 | Parameters
148 | ==================
149 |
150 | There are several environment variables to setting runtime parameters:
151 |
152 | - `NVIDIA_SMI_EXPORTER_BINARY` - path to nvidia-smi executive binary, default: `$(which nvidia-smi)`
153 |
154 | - `NVIDIA_SMI_EXPORTER_PORT` - a port where the server will be started, default: `9454`
155 |
156 | - `NVIDIA_SMI_EXPORTER_HOST` - a host where the server will be started, default: `0.0.0.0`
157 |
158 | - `NVIDIA_SMI_EXPORTER_NAME_PREFIX` - prefix for every parameter name in output, default: `nvidia_smi_`
159 |
160 | - `NVIDIA_SMI_EXPORTER_SOURCE` - source to processing - `xml` or `csv`, default: `xml`.
161 |
162 |
163 | When `NVIDIA_SMI_EXPORTER_SOURCE` == `csv`:
164 |
165 | - `NVIDIA_SMI_EXPORTER_QUERY` - comma-separated list to query parameters from nvidia-smi, default: `clocks.current.graphics,clocks.current.memory,clocks.current.sm,clocks.current.video,clocks.max.graphics,clocks.max.memory,clocks.max.sm,fan.speed,memory.total,memory.used,power.draw,power.limit,temperature.gpu,utilization.gpu,utilization.memory`
166 |
--------------------------------------------------------------------------------
/app/application.rb:
--------------------------------------------------------------------------------
1 | require 'open3'
2 | require_relative 'exporter'
3 |
4 | class Application
5 | def initialize
6 | Thread.abort_on_exception = true
7 |
8 | ENV['NVIDIA_SMI_EXPORTER_SOURCE'] ||= 'xml'
9 | ENV['NVIDIA_SMI_EXPORTER_PORT'] ||= '9454'
10 | ENV['NVIDIA_SMI_EXPORTER_HOST'] ||= '0.0.0.0'
11 | ENV['NVIDIA_SMI_EXPORTER_NAME_PREFIX'] ||= 'nvidia_smi_'
12 |
13 | ENV['NVIDIA_SMI_EXPORTER_QUERY'] ||= %W(
14 | clocks.current.graphics
15 | clocks.current.memory
16 | clocks.current.sm
17 | clocks.current.video
18 | clocks.max.graphics
19 | clocks.max.memory
20 | clocks.max.sm
21 | fan.speed
22 | memory.total
23 | memory.used
24 | power.draw
25 | power.limit
26 | temperature.gpu
27 | utilization.gpu
28 | utilization.memory
29 | ).join(',')
30 |
31 | ENV['NVIDIA_SMI_EXPORTER_BINARY'] ||= begin
32 | stdout_str, status = Open3.capture2('which nvidia-smi')
33 | status.exitstatus.zero? ? stdout_str.strip : nil
34 | end
35 | end
36 |
37 | def run!
38 | Exporter.run!
39 | end
40 | end
41 |
42 | Application.new.run!
43 |
--------------------------------------------------------------------------------
/app/exporter.rb:
--------------------------------------------------------------------------------
1 | require 'sinatra/base'
2 | require_relative 'n_vidia_smi'
3 | require_relative 'n_vidia_smi_xml'
4 |
5 | class Exporter < Sinatra::Base
6 | set :traps, false
7 | set :server, :puma
8 | set :port, proc { ENV['NVIDIA_SMI_EXPORTER_PORT'].to_i }
9 | set :bind, proc { ENV['NVIDIA_SMI_EXPORTER_HOST'] }
10 | set :show_exceptions, false
11 |
12 | not_found do
13 | halt 404
14 | end
15 |
16 | error do
17 | halt 500
18 | end
19 |
20 | get '/metrics' do
21 | content_type 'text/plain'
22 |
23 | processor =
24 | case ENV['NVIDIA_SMI_EXPORTER_SOURCE']
25 | when 'csv'
26 | NVidiaSMI.new(
27 | binary_path: ENV['NVIDIA_SMI_EXPORTER_BINARY'],
28 | name_prefix: ENV['NVIDIA_SMI_EXPORTER_NAME_PREFIX'],
29 | query_list: ENV['NVIDIA_SMI_EXPORTER_QUERY'].to_s.split(','))
30 | when 'xml'
31 | NVidiaSMI_XML.new(
32 | binary_path: ENV['NVIDIA_SMI_EXPORTER_BINARY'],
33 | name_prefix: ENV['NVIDIA_SMI_EXPORTER_NAME_PREFIX'])
34 | else
35 | raise("Unknown value `#{ENV['NVIDIA_SMI_EXPORTER_SOURCE']}' in NVIDIA_SMI_EXPORTER_SOURCE")
36 | end
37 |
38 | response = processor.query
39 | data = processor.parse(response)
40 | processor.format_prometheus(data)
41 | end
42 |
43 | get '/ping' do
44 | halt 200, 'OK'
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/app/n_vidia_smi.rb:
--------------------------------------------------------------------------------
1 | require 'active_support/core_ext/object/blank'
2 |
3 | class NVidiaSMI
4 | attr_reader :binary_path, :name_prefix, :query_list
5 |
6 | def initialize(binary_path:, query_list:, name_prefix: nil)
7 | @binary_path = binary_path
8 | @name_prefix = name_prefix
9 | @query_list = query_list
10 | end
11 |
12 | def query(query_list = @query_list)
13 | unless @binary_path.present?
14 | raise("Don't know path to nvidia-smi binary")
15 | end
16 |
17 | # Move uuid to first position
18 | query_list = ['uuid'] + (query_list - ['uuid'])
19 |
20 | query_string = query_list.join(',')
21 | stdout_and_stderr_str, status = Open3.capture2e(@binary_path, '--format=csv', "--query-gpu=#{query_string}")
22 |
23 | unless status.exitstatus.zero?
24 | raise(stdout_and_stderr_str)
25 | end
26 |
27 | stdout_and_stderr_str
28 | end
29 |
30 | def parse(str)
31 | lines = str.strip.split("\n")
32 | arrs = lines.inject([]) { |arr, line| arr << line.split(',').map(&:strip) }
33 |
34 | result = {}
35 |
36 | headers, *line_arrs = arrs
37 | return result if line_arrs.blank?
38 |
39 | headers.each_with_index do |column, index|
40 | raise('First column is not uuid') if index.zero? && column != 'uuid'
41 | next if index.zero?
42 |
43 | case column
44 | when /\A([^\[]+)\[(%)\]\z/
45 | multiplicator = 0.01
46 | unit = $2
47 | name_postfix = ''
48 | when /\A([^\[]+)\[(MiB)\]\z/
49 | multiplicator = 1_048_576
50 | unit = $2
51 | name_postfix = '_bytes'
52 | when /\A([^\[]+)\[(W)\]\z/
53 | multiplicator = 1
54 | unit = $2
55 | name_postfix = '_watts'
56 | when /\A([^\[]+)\[(MHz)\]\z/
57 | multiplicator = 1_000_000
58 | unit = $2
59 | name_postfix = '_hz'
60 | when /\A([^\[\]]+)\z/
61 | multiplicator = 1
62 | unit = ''
63 | name_postfix = ''
64 | else
65 | raise("Unknown what to do with string `#{column}'")
66 | end
67 | name = $1.strip.downcase.gsub('.', '_')
68 | if column.include?('temperature') && name_postfix.blank?
69 | name_postfix = '_celsius'
70 | end
71 |
72 | line_arrs.each do |line_arr|
73 | field_str = line_arr[index]
74 | field_value =
75 | begin
76 | Integer(field_str.sub(unit, '').strip)
77 | rescue ArgumentError
78 | Float(field_str.sub(unit, '').strip)
79 | end
80 | field_value *= multiplicator
81 |
82 | uuid = line_arr[0].sub(/\AGPU-/, '')
83 | result[uuid] ||= {}
84 | result[uuid]["#{name}#{name_postfix}"] = field_value
85 | end
86 | end
87 | result
88 | end
89 |
90 | def format_prometheus(data_hash)
91 | output_list = []
92 | data_hash.each do |uuid, options|
93 | options.each do |name, value|
94 | output_list << "#{@name_prefix}#{name}{uuid=\"#{uuid}\"} #{value}"
95 | end
96 | end
97 | output_list.join("\n") + "\n"
98 | end
99 | end
100 |
--------------------------------------------------------------------------------
/app/n_vidia_smi_xml.rb:
--------------------------------------------------------------------------------
1 | require 'active_support/core_ext/object/blank'
2 | require 'nokogiri'
3 |
4 | class NVidiaSMI_XML
5 | attr_reader :binary_path, :name_prefix
6 |
7 | def initialize(binary_path:, name_prefix: nil)
8 | @binary_path = binary_path
9 | @name_prefix = name_prefix
10 | end
11 |
12 | def query
13 | unless @binary_path.present?
14 | raise("Don't know path to nvidia-smi binary")
15 | end
16 |
17 | stdout_and_stderr_str, status = Open3.capture2e(@binary_path, '--query', '--xml-format')
18 |
19 | unless status.exitstatus.zero?
20 | raise(stdout_and_stderr_str)
21 | end
22 |
23 | stdout_and_stderr_str
24 | end
25 |
26 | def parse(str)
27 | doc = Nokogiri::XML(str)
28 | output = {}
29 |
30 | if (nodes = doc.xpath('/nvidia_smi_log/attached_gpus/text()')).size == 1
31 | path, data = 'attached_gpus', nodes[0].content.strip
32 | if (path, data = normalize_data(path, data))
33 | output[path] = { {} => data }
34 | end
35 | end
36 |
37 | # traverse every node in every gpu branch
38 | doc.xpath('/nvidia_smi_log/gpu').each do |node|
39 | pci_bus_id = node.get_attribute('id')
40 | root_path = "#{node.path}/"
41 | uuid = node.xpath('./uuid')[0]&.content
42 | if uuid =~ /^GPU-/
43 | uuid = uuid.slice(4..-1)
44 | end
45 |
46 | node.traverse do |sub_node|
47 | # skip not leaf
48 | if sub_node.element? && sub_node.children.size == 1 && (text_el = sub_node.children[0]).text? &&
49 | # skip N/A мфдгу
50 | (data = text_el.content.strip) != 'N/A' &&
51 | # skip empty value
52 | data != ''
53 |
54 | # cut common path /nvidia_smi_log/gpu[x]
55 | local_path = sub_node.path
56 | if local_path.slice(0, root_path.size) == root_path
57 | local_path = local_path.slice(root_path.size..-1)
58 | end
59 |
60 | # TODO don't skip paths within array like a
61 | # /nvidia_smi_log/gpu[2]/processes/process_info[1]/pid <= 450
62 | # /nvidia_smi_log/gpu[2]/processes/process_info[1]/type <= G
63 | # /nvidia_smi_log/gpu[2]/processes/process_info[1]/process_name <= /usr/lib/xorg/Xorg
64 | # /nvidia_smi_log/gpu[2]/processes/process_info[1]/used_memory <= 5 MiB
65 | if local_path !~ /\[\d+\]/
66 | local_path, data = normalize_data(local_path, data)
67 | unless local_path.nil?
68 | output[local_path] ||= {}
69 | output[local_path][{ uuid: uuid }] = data
70 | end
71 | end
72 | end
73 | end
74 | end
75 | output
76 | end
77 |
78 | def format_prometheus(hash)
79 | output_list = []
80 | hash.each do |path, values|
81 | values.each do |labels_hash, value|
82 | name = path.gsub('/', '_')
83 | labels = format_labels(labels_hash)
84 | output_list << "#{@name_prefix}#{name}#{labels} #{value}"
85 | end
86 | end
87 | output_list.join("\n") + "\n"
88 | end
89 |
90 | private
91 |
92 | def normalize_data(path, data)
93 | num = '\d+(?:\.\d+)?'
94 |
95 | case data
96 |
97 | when /^(#{num})\sB$/
98 | return ["#{path}_bytes", ($1.to_f).to_i]
99 | when /^(#{num})\sKiB$/
100 | return ["#{path}_bytes", ($1.to_f * 1024).to_i]
101 | when /^(#{num})\sMiB$/
102 | return ["#{path}_bytes", ($1.to_f * 1024 * 1024).to_i]
103 | when /^(#{num})\sGiB$/
104 | return ["#{path}_bytes", ($1.to_f * 1024 * 1024 * 1024).to_i]
105 |
106 | when /^(#{num})\sHz$/
107 | return ["#{path}_hz", $1.to_f]
108 | when /^(#{num})\sKHz$/
109 | return ["#{path}_hz", $1.to_f * 1000]
110 | when /^(#{num})\sMHz$/
111 | return ["#{path}_hz", $1.to_f * 1000 * 1000]
112 | when /^(#{num})\sGHz$/
113 | return ["#{path}_hz", $1.to_f * 1000 * 1000 * 1000]
114 |
115 | when /^(#{num})\s%$/
116 | return ["#{path}_ratio", $1.to_f / 100.0]
117 |
118 | when /^(#{num})\sC$/
119 | return ["#{path}_celsius", $1.to_f]
120 |
121 | when /^(#{num})\sW$/
122 | return ["#{path}_watts", $1.to_f]
123 | when /^(#{num})\sKW$/
124 | return ["#{path}_watts", $1.to_f * 1000.0]
125 |
126 | when /^(#{num})\sB\/s$/
127 | return ["#{path}_bytes_per_second", ($1.to_f).to_i]
128 | when /^(#{num})\sKB\/s$/
129 | return ["#{path}_bytes_per_second", ($1.to_f * 1024).to_i]
130 | when /^(#{num})\sMB\/s$/
131 | return ["#{path}_bytes_per_second", ($1.to_f * 1024 * 1024).to_i]
132 | when /^(#{num})\sGB\/s$/
133 | return ["#{path}_bytes_per_second", ($1.to_f * 1024 * 1024 * 1024).to_i]
134 |
135 | when /^P(\d{1,2})$/
136 | return [path, $1.to_i]
137 |
138 | when 'Disabled', 'Not Active', 'No', 'Not Supported', 'Unsupported'
139 | return [path, 0]
140 | when 'Enabled', 'Active', 'Yes', 'Supported'
141 | return [path, 1]
142 | when '1x', '2x', '4x', '8x', '16x', '32x'
143 | return [path, data.to_i]
144 |
145 | # compute_mode = 0/Default, 1/Exclusive_Thread, 2/Prohibited, 3/Exclusive_Process
146 |
147 | else
148 | case path
149 | when /compute_mode$/
150 | h = { 'Default' => 0, 'Exclusive_Thread' => 1, 'Prohibited' => 2, 'Exclusive_Process' => 3 }
151 | return nil unless h.key?(data)
152 | return [path, h[data]]
153 |
154 | else
155 | return [path, data] if data.to_f.to_s == data
156 | return [path, data] if data.to_i.to_s == data
157 |
158 | return nil
159 | end
160 | end
161 | end
162 |
163 | def format_labels(hash)
164 | list = hash.map do |k, v|
165 | "#{k}=\"#{v}\""
166 | end
167 | list == [] ? '' : "{#{list.join(',')}}"
168 | end
169 | end
170 |
--------------------------------------------------------------------------------
/spec/fixtures/nvidia-smi-1.csv:
--------------------------------------------------------------------------------
1 | uuid, memory.used [MiB], utilization.gpu [%], temperature.gpu, power.draw [W], clocks.current.sm [MHz]
2 | GPU-d86c351b-8f94-33ab-3b97-accb421fef6d, 754 MiB, 100 %, 71, 217.24 W, 1949 MHz
3 | GPU-683c6e09-3969-31a5-b7ca-cc88252b7fce, 641 MiB, 100 %, 71, 208.30 W, 2025 MHz
4 |
--------------------------------------------------------------------------------
/spec/fixtures/nvidia-smi-2.csv:
--------------------------------------------------------------------------------
1 | uuid, fan.speed [%], temperature.gpu, power.draw [W], power.limit [W], utilization.gpu [%], utilization.memory [%], memory.used [MiB], memory.total [MiB], clocks.current.graphics [MHz], clocks.max.graphics [MHz], clocks.current.sm [MHz], clocks.current.memory [MHz], clocks.max.memory [MHz]
2 | GPU-20fe89bc-c8ef-5a9f-078e-efa3324d790b, 63 %, 73, 213.07 W, 216.00 W, 100 %, 87 %, 754 MiB, 8119 MiB, 1987 MHz, 1999 MHz, 1987 MHz, 5130 MHz, 5005 MHz
3 | GPU-68988cf6-8de9-6585-a263-d2e3ea96b75a, 81 %, 67, 187.04 W, 216.00 W, 100 %, 90 %, 586 MiB, 4043 MiB, 1453 MHz, 1606 MHz, 1453 MHz, 3004 MHz, 3505 MHz
4 | GPU-90e3dab0-b59d-8bf6-d909-d4fab8d2f29b, 55 %, 68, 206.44 W, 216.00 W, 100 %, 87 %, 641 MiB, 8119 MiB, 1949 MHz, 1936 MHz, 1949 MHz, 5130 MHz, 5005 MHz
5 |
--------------------------------------------------------------------------------
/spec/fixtures/nvidia-smi-3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Sat Feb 27 02:47:26 2021
5 | 460.27.04
6 | 11.2
7 | 2
8 |
9 | GeForce GTX 1080
10 | GeForce
11 | Enabled
12 | Disabled
13 | Enabled
14 |
15 | N/A
16 | N/A
17 |
18 |
19 | None
20 |
21 | Disabled
22 | 4000
23 |
24 | N/A
25 | N/A
26 |
27 | N/A
28 | GPU-683c6e09-3969-31a5-b7ca-cc88252b7fce
29 | 0
30 | 86.04.60.00.B4
31 | No
32 | 0x100
33 | N/A
34 |
35 | G001.0000.01.04
36 | 1.1
37 | N/A
38 | N/A
39 |
40 |
41 | N/A
42 | N/A
43 |
44 |
45 | None
46 | N/A
47 |
48 |
49 | N/A
50 |
51 |
52 | 01
53 | 00
54 | 0000
55 | 1B8010DE
56 | 00000000:01:00.0
57 | 37021458
58 |
59 |
60 | 3
61 | 3
62 |
63 |
64 | 16x
65 | 1x
66 |
67 |
68 |
69 | N/A
70 | N/A
71 |
72 | 65535
73 | 0
74 | 11000 KB/s
75 | 31000 KB/s
76 |
77 | 53 %
78 | P2
79 |
80 | Not Active
81 | Not Active
82 |
83 | Active
84 | Not Active
85 | Not Active
86 | Not Active
87 | Not Active
88 | Not Active
89 | Not Active
90 |
91 |
92 | 8116 MiB
93 | 2900 MiB
94 | 5216 MiB
95 |
96 |
97 | 256 MiB
98 | 5 MiB
99 | 251 MiB
100 |
101 | Default
102 |
103 | 100 %
104 | 100 %
105 | 0 %
106 | 0 %
107 |
108 |
109 | 0
110 | 0
111 | 0
112 |
113 |
114 | 0
115 | 0
116 | 0
117 |
118 |
119 | N/A
120 | N/A
121 |
122 |
123 |
124 |
125 | N/A
126 | N/A
127 | N/A
128 | N/A
129 | N/A
130 | N/A
131 | N/A
132 | N/A
133 |
134 |
135 | N/A
136 | N/A
137 | N/A
138 | N/A
139 | N/A
140 | N/A
141 | N/A
142 | N/A
143 |
144 |
145 |
146 |
147 | N/A
148 | N/A
149 | N/A
150 | N/A
151 | N/A
152 | N/A
153 | N/A
154 | N/A
155 |
156 |
157 | N/A
158 | N/A
159 | N/A
160 | N/A
161 | N/A
162 | N/A
163 | N/A
164 | N/A
165 |
166 |
167 |
168 |
169 |
170 | N/A
171 | N/A
172 |
173 |
174 | N/A
175 | N/A
176 |
177 | N/A
178 | N/A
179 |
180 | N/A
181 |
182 | 67 C
183 | 96 C
184 | 93 C
185 | N/A
186 | 83 C
187 | N/A
188 | N/A
189 |
190 |
191 | 60 C
192 | 92 C
193 |
194 |
195 | P2
196 | Supported
197 | 211.86 W
198 | 216.00 W
199 | 200.00 W
200 | 216.00 W
201 | 100.00 W
202 | 216.00 W
203 |
204 |
205 | 1784 MHz
206 | 1784 MHz
207 | 5514 MHz
208 | 1594 MHz
209 |
210 |
211 | N/A
212 | N/A
213 |
214 |
215 | N/A
216 | N/A
217 |
218 |
219 | 1999 MHz
220 | 1999 MHz
221 | 5005 MHz
222 | 1708 MHz
223 |
224 |
225 | N/A
226 |
227 |
228 | N/A
229 | N/A
230 |
231 | N/A
232 |
233 |
234 | N/A
235 | N/A
236 | 450
237 | G
238 | /usr/lib/xorg/Xorg
239 | 12 MiB
240 |
241 |
242 | N/A
243 | N/A
244 | 8991
245 | C
246 | /opt/nbminer/nbminer
247 | 2883 MiB
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 | GeForce GTX 1080
256 | GeForce
257 | Disabled
258 | Disabled
259 | Enabled
260 |
261 | N/A
262 | N/A
263 |
264 |
265 | None
266 |
267 | Disabled
268 | 4000
269 |
270 | N/A
271 | N/A
272 |
273 | N/A
274 | GPU-90e3dab0-b59d-8bf6-d909-d4fab8d2f29b
275 | 1
276 | 86.04.60.00.BD
277 | No
278 | 0x300
279 | N/A
280 |
281 | G001.0000.01.04
282 | 1.1
283 | N/A
284 | N/A
285 |
286 |
287 | N/A
288 | N/A
289 |
290 |
291 | None
292 | N/A
293 |
294 |
295 | N/A
296 |
297 |
298 | 03
299 | 00
300 | 0000
301 | 1B8010DE
302 | 00000000:03:00.0
303 | 37171458
304 |
305 |
306 | 3
307 | 3
308 |
309 |
310 | 16x
311 | 1x
312 |
313 |
314 |
315 | N/A
316 | N/A
317 |
318 | 552
319 | 0
320 | 11000 KB/s
321 | 31000 KB/s
322 |
323 | 58 %
324 | P2
325 |
326 | Not Active
327 | Not Active
328 |
329 | Active
330 | Not Active
331 | Not Active
332 | Not Active
333 | Not Active
334 | Not Active
335 | Not Active
336 |
337 |
338 | 8119 MiB
339 | 2893 MiB
340 | 5226 MiB
341 |
342 |
343 | 256 MiB
344 | 5 MiB
345 | 251 MiB
346 |
347 | Default
348 |
349 | 100 %
350 | 100 %
351 | 0 %
352 | 0 %
353 |
354 |
355 | 0
356 | 0
357 | 0
358 |
359 |
360 | 0
361 | 0
362 | 0
363 |
364 |
365 | N/A
366 | N/A
367 |
368 |
369 |
370 |
371 | N/A
372 | N/A
373 | N/A
374 | N/A
375 | N/A
376 | N/A
377 | N/A
378 | N/A
379 |
380 |
381 | N/A
382 | N/A
383 | N/A
384 | N/A
385 | N/A
386 | N/A
387 | N/A
388 | N/A
389 |
390 |
391 |
392 |
393 | N/A
394 | N/A
395 | N/A
396 | N/A
397 | N/A
398 | N/A
399 | N/A
400 | N/A
401 |
402 |
403 | N/A
404 | N/A
405 | N/A
406 | N/A
407 | N/A
408 | N/A
409 | N/A
410 | N/A
411 |
412 |
413 |
414 |
415 |
416 | N/A
417 | N/A
418 |
419 |
420 | N/A
421 | N/A
422 |
423 | N/A
424 | N/A
425 |
426 | N/A
427 |
428 | 70 C
429 | 96 C
430 | 93 C
431 | N/A
432 | 83 C
433 | N/A
434 | N/A
435 |
436 |
437 | 60 C
438 | 92 C
439 |
440 |
441 | P2
442 | Supported
443 | 211.06 W
444 | 216.00 W
445 | 200.00 W
446 | 216.00 W
447 | 100.00 W
448 | 216.00 W
449 |
450 |
451 | 1657 MHz
452 | 1657 MHz
453 | 5514 MHz
454 | 1480 MHz
455 |
456 |
457 | N/A
458 | N/A
459 |
460 |
461 | N/A
462 | N/A
463 |
464 |
465 | 1936 MHz
466 | 1936 MHz
467 | 5005 MHz
468 | 1708 MHz
469 |
470 |
471 | N/A
472 |
473 |
474 | N/A
475 | N/A
476 |
477 | N/A
478 |
479 |
480 | N/A
481 | N/A
482 | 450
483 | G
484 | /usr/lib/xorg/Xorg
485 | 5 MiB
486 |
487 |
488 | N/A
489 | N/A
490 | 8991
491 | C
492 | /opt/nbminer/nbminer
493 | 2883 MiB
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
--------------------------------------------------------------------------------
/spec/fixtures/nvidia-smi-4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Fri Sep 27 11:00:44 2019
5 | 418.56
6 | 10.1
7 | 1
8 |
9 | Quadro P2000
10 | Quadro
11 | Disabled
12 | Disabled
13 | Disabled
14 | Disabled
15 | 4000
16 |
17 | N/A
18 | N/A
19 |
20 | 0324217004816
21 | GPU-1ffe36ef-ac55-60ad-f9cf-623871e7736d
22 | 0
23 | 86.06.3F.00.0D
24 | No
25 | 0x400
26 | 900-5G410-1700-000
27 |
28 | G410.0502.00.02
29 | 1.1
30 | N/A
31 | N/A
32 |
33 |
34 | N/A
35 | N/A
36 |
37 |
38 | None
39 |
40 |
41 | N/A
42 |
43 |
44 | 04
45 | 00
46 | 0000
47 | 1C3010DE
48 | 00000000:04:00.0
49 | 11B310DE
50 |
51 |
52 | 3
53 | 3
54 |
55 |
56 | 16x
57 | 16x
58 |
59 |
60 |
61 | N/A
62 | N/A
63 |
64 | 0
65 | 0
66 | 0 KB/s
67 | 0 KB/s
68 |
69 | 61 %
70 | P0
71 |
72 | Not Active
73 | Not Active
74 |
75 | Not Active
76 | Not Active
77 | Not Active
78 | Not Active
79 | Not Active
80 | Not Active
81 | Not Active
82 |
83 |
84 | 5059 MiB
85 | 319 MiB
86 | 4740 MiB
87 |
88 |
89 | 256 MiB
90 | 2 MiB
91 | 254 MiB
92 |
93 | Default
94 |
95 | 0 %
96 | 0 %
97 | 0 %
98 | 0 %
99 |
100 |
101 | 0
102 | 0
103 | 0
104 |
105 |
106 | 0
107 | 0
108 | 0
109 |
110 |
111 | N/A
112 | N/A
113 |
114 |
115 |
116 |
117 | N/A
118 | N/A
119 | N/A
120 | N/A
121 | N/A
122 | N/A
123 | N/A
124 | N/A
125 |
126 |
127 | N/A
128 | N/A
129 | N/A
130 | N/A
131 | N/A
132 | N/A
133 | N/A
134 | N/A
135 |
136 |
137 |
138 |
139 | N/A
140 | N/A
141 | N/A
142 | N/A
143 | N/A
144 | N/A
145 | N/A
146 | N/A
147 |
148 |
149 | N/A
150 | N/A
151 | N/A
152 | N/A
153 | N/A
154 | N/A
155 | N/A
156 | N/A
157 |
158 |
159 |
160 |
161 |
162 | N/A
163 | N/A
164 |
165 |
166 | N/A
167 | N/A
168 |
169 | N/A
170 |
171 |
172 | 62 C
173 | 104 C
174 | 101 C
175 | N/A
176 | N/A
177 | N/A
178 |
179 |
180 | P0
181 | Supported
182 | 20.32 W
183 | 75.00 W
184 | 75.00 W
185 | 75.00 W
186 | 75.00 W
187 | 75.00 W
188 |
189 |
190 | 1215 MHz
191 | 1215 MHz
192 | 3499 MHz
193 | 1101 MHz
194 |
195 |
196 | 1075 MHz
197 | 3504 MHz
198 |
199 |
200 | 1075 MHz
201 | 3504 MHz
202 |
203 |
204 | 1721 MHz
205 | 1721 MHz
206 | 3504 MHz
207 | 1556 MHz
208 |
209 |
210 | 1721 MHz
211 |
212 |
213 | N/A
214 | N/A
215 |
216 |
217 |
218 | 3504 MHz
219 | 1721 MHz
220 | 1708 MHz
221 | 1695 MHz
222 | 1683 MHz
223 | 1670 MHz
224 | 1657 MHz
225 | 1645 MHz
226 | 1632 MHz
227 | 1620 MHz
228 | 1607 MHz
229 | 1594 MHz
230 | 1582 MHz
231 | 1569 MHz
232 | 1556 MHz
233 | 1544 MHz
234 | 1531 MHz
235 | 1518 MHz
236 | 1506 MHz
237 | 1493 MHz
238 | 1480 MHz
239 | 1468 MHz
240 | 1455 MHz
241 | 1442 MHz
242 | 1430 MHz
243 | 1417 MHz
244 | 1404 MHz
245 | 1392 MHz
246 | 1379 MHz
247 | 1366 MHz
248 | 1354 MHz
249 | 1341 MHz
250 | 1328 MHz
251 | 1316 MHz
252 | 1303 MHz
253 | 1290 MHz
254 | 1278 MHz
255 | 1265 MHz
256 | 1252 MHz
257 | 1240 MHz
258 | 1227 MHz
259 | 1215 MHz
260 | 1202 MHz
261 | 1189 MHz
262 | 1177 MHz
263 | 1164 MHz
264 | 1151 MHz
265 | 1139 MHz
266 | 1126 MHz
267 | 1113 MHz
268 | 1101 MHz
269 | 1088 MHz
270 | 1075 MHz
271 | 1063 MHz
272 | 1050 MHz
273 | 1037 MHz
274 | 1025 MHz
275 | 1012 MHz
276 | 999 MHz
277 | 987 MHz
278 | 974 MHz
279 | 961 MHz
280 | 949 MHz
281 | 936 MHz
282 | 923 MHz
283 | 911 MHz
284 | 898 MHz
285 | 885 MHz
286 | 873 MHz
287 | 860 MHz
288 | 847 MHz
289 | 835 MHz
290 | 822 MHz
291 | 810 MHz
292 | 797 MHz
293 | 784 MHz
294 | 772 MHz
295 | 759 MHz
296 | 746 MHz
297 | 734 MHz
298 | 721 MHz
299 | 708 MHz
300 | 696 MHz
301 | 683 MHz
302 | 670 MHz
303 | 658 MHz
304 | 645 MHz
305 | 632 MHz
306 | 620 MHz
307 | 607 MHz
308 | 594 MHz
309 | 582 MHz
310 | 569 MHz
311 | 556 MHz
312 | 544 MHz
313 | 531 MHz
314 | 518 MHz
315 | 506 MHz
316 | 493 MHz
317 | 480 MHz
318 | 468 MHz
319 | 455 MHz
320 | 442 MHz
321 | 430 MHz
322 | 417 MHz
323 | 405 MHz
324 | 392 MHz
325 | 379 MHz
326 | 367 MHz
327 | 354 MHz
328 | 341 MHz
329 | 329 MHz
330 | 316 MHz
331 | 303 MHz
332 | 291 MHz
333 | 278 MHz
334 | 265 MHz
335 | 253 MHz
336 | 240 MHz
337 | 227 MHz
338 | 215 MHz
339 | 202 MHz
340 | 189 MHz
341 | 177 MHz
342 | 164 MHz
343 | 151 MHz
344 | 139 MHz
345 |
346 |
347 | 810 MHz
348 | 1721 MHz
349 | 1708 MHz
350 | 1695 MHz
351 | 1683 MHz
352 | 1670 MHz
353 | 1657 MHz
354 | 1645 MHz
355 | 1632 MHz
356 | 1620 MHz
357 | 1607 MHz
358 | 1594 MHz
359 | 1582 MHz
360 | 1569 MHz
361 | 1556 MHz
362 | 1544 MHz
363 | 1531 MHz
364 | 1518 MHz
365 | 1506 MHz
366 | 1493 MHz
367 | 1480 MHz
368 | 1468 MHz
369 | 1455 MHz
370 | 1442 MHz
371 | 1430 MHz
372 | 1417 MHz
373 | 1404 MHz
374 | 1392 MHz
375 | 1379 MHz
376 | 1366 MHz
377 | 1354 MHz
378 | 1341 MHz
379 | 1328 MHz
380 | 1316 MHz
381 | 1303 MHz
382 | 1290 MHz
383 | 1278 MHz
384 | 1265 MHz
385 | 1252 MHz
386 | 1240 MHz
387 | 1227 MHz
388 | 1215 MHz
389 | 1202 MHz
390 | 1189 MHz
391 | 1177 MHz
392 | 1164 MHz
393 | 1151 MHz
394 | 1139 MHz
395 | 1126 MHz
396 | 1113 MHz
397 | 1101 MHz
398 | 1088 MHz
399 | 1075 MHz
400 | 1063 MHz
401 | 1050 MHz
402 | 1037 MHz
403 | 1025 MHz
404 | 1012 MHz
405 | 999 MHz
406 | 987 MHz
407 | 974 MHz
408 | 961 MHz
409 | 949 MHz
410 | 936 MHz
411 | 923 MHz
412 | 911 MHz
413 | 898 MHz
414 | 885 MHz
415 | 873 MHz
416 | 860 MHz
417 | 847 MHz
418 | 835 MHz
419 | 822 MHz
420 | 810 MHz
421 | 797 MHz
422 | 784 MHz
423 | 772 MHz
424 | 759 MHz
425 | 746 MHz
426 | 734 MHz
427 | 721 MHz
428 | 708 MHz
429 | 696 MHz
430 | 683 MHz
431 | 670 MHz
432 | 658 MHz
433 | 645 MHz
434 | 632 MHz
435 | 620 MHz
436 | 607 MHz
437 | 594 MHz
438 | 582 MHz
439 | 569 MHz
440 | 556 MHz
441 | 544 MHz
442 | 531 MHz
443 | 518 MHz
444 | 506 MHz
445 | 493 MHz
446 | 480 MHz
447 | 468 MHz
448 | 455 MHz
449 | 442 MHz
450 | 430 MHz
451 | 417 MHz
452 | 405 MHz
453 | 392 MHz
454 | 379 MHz
455 | 367 MHz
456 | 354 MHz
457 | 341 MHz
458 | 329 MHz
459 | 316 MHz
460 | 303 MHz
461 | 291 MHz
462 | 278 MHz
463 | 265 MHz
464 | 253 MHz
465 | 240 MHz
466 | 227 MHz
467 | 215 MHz
468 | 202 MHz
469 | 189 MHz
470 | 177 MHz
471 | 164 MHz
472 | 151 MHz
473 | 139 MHz
474 |
475 |
476 | 405 MHz
477 | 607 MHz
478 | 594 MHz
479 | 582 MHz
480 | 569 MHz
481 | 556 MHz
482 | 544 MHz
483 | 531 MHz
484 | 518 MHz
485 | 506 MHz
486 | 493 MHz
487 | 480 MHz
488 | 468 MHz
489 | 455 MHz
490 | 442 MHz
491 | 430 MHz
492 | 417 MHz
493 | 405 MHz
494 | 392 MHz
495 | 379 MHz
496 | 367 MHz
497 | 354 MHz
498 | 341 MHz
499 | 329 MHz
500 | 316 MHz
501 | 303 MHz
502 | 291 MHz
503 | 278 MHz
504 | 265 MHz
505 | 253 MHz
506 | 240 MHz
507 | 227 MHz
508 | 215 MHz
509 | 202 MHz
510 | 189 MHz
511 | 177 MHz
512 | 164 MHz
513 | 151 MHz
514 | 139 MHz
515 |
516 |
517 |
518 |
519 | 7134
520 | C
521 | /usr/lib/plexmediaserver/Plex Transcoder
522 | 309 MiB
523 |
524 |
525 |
526 |
527 |
528 |
529 |
--------------------------------------------------------------------------------
/spec/fixtures/parsed-1.json:
--------------------------------------------------------------------------------
1 | {
2 | "d86c351b-8f94-33ab-3b97-accb421fef6d": {
3 | "memory_used_bytes": 790626304,
4 | "utilization_gpu": 1.0,
5 | "temperature_gpu_celsius": 71,
6 | "power_draw_watts": 217.24,
7 | "clocks_current_sm_hz": 1949000000
8 | },
9 | "683c6e09-3969-31a5-b7ca-cc88252b7fce": {
10 | "memory_used_bytes": 672137216,
11 | "utilization_gpu": 1.0,
12 | "temperature_gpu_celsius": 71,
13 | "power_draw_watts": 208.3,
14 | "clocks_current_sm_hz": 2025000000
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/spec/fixtures/parsed-2.json:
--------------------------------------------------------------------------------
1 | {
2 | "20fe89bc-c8ef-5a9f-078e-efa3324d790b": {
3 | "fan_speed": 0.63,
4 | "temperature_gpu_celsius": 73,
5 | "power_draw_watts": 213.07,
6 | "power_limit_watts": 216.0,
7 | "utilization_gpu": 1.0,
8 | "utilization_memory": 0.87,
9 | "memory_used_bytes": 790626304,
10 | "memory_total_bytes": 8513388544,
11 | "clocks_current_graphics_hz": 1987000000,
12 | "clocks_max_graphics_hz": 1999000000,
13 | "clocks_current_sm_hz": 1987000000,
14 | "clocks_current_memory_hz": 5130000000,
15 | "clocks_max_memory_hz": 5005000000
16 | },
17 | "68988cf6-8de9-6585-a263-d2e3ea96b75a": {
18 | "fan_speed": 0.81,
19 | "temperature_gpu_celsius": 67,
20 | "power_draw_watts": 187.04,
21 | "power_limit_watts": 216.0,
22 | "utilization_gpu": 1.0,
23 | "utilization_memory": 0.9,
24 | "memory_used_bytes": 614465536,
25 | "memory_total_bytes": 4239392768,
26 | "clocks_current_graphics_hz": 1453000000,
27 | "clocks_max_graphics_hz": 1606000000,
28 | "clocks_current_sm_hz": 1453000000,
29 | "clocks_current_memory_hz": 3004000000,
30 | "clocks_max_memory_hz": 3505000000
31 | },
32 | "90e3dab0-b59d-8bf6-d909-d4fab8d2f29b": {
33 | "fan_speed": 0.55,
34 | "temperature_gpu_celsius": 68,
35 | "power_draw_watts": 206.44,
36 | "power_limit_watts": 216.0,
37 | "utilization_gpu": 1.0,
38 | "utilization_memory": 0.87,
39 | "memory_used_bytes": 672137216,
40 | "memory_total_bytes": 8513388544,
41 | "clocks_current_graphics_hz": 1949000000,
42 | "clocks_max_graphics_hz": 1936000000,
43 | "clocks_current_sm_hz": 1949000000,
44 | "clocks_current_memory_hz": 5130000000,
45 | "clocks_max_memory_hz": 5005000000
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/spec/helpers/fixture.rb:
--------------------------------------------------------------------------------
1 | module Fixture
2 | def fixture_load(name)
3 | file_name = File.expand_path("../../fixtures/#{name}", __FILE__)
4 | File.read(file_name)
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/n_vidia_smi_spec.rb:
--------------------------------------------------------------------------------
1 | RSpec.describe NVidiaSMI do
2 | subject { described_class.new(binary_path: nil, query_list: nil, name_prefix: nil) }
3 |
4 | describe '#parser' do
5 | it { expect(subject.parse(fixture_load('nvidia-smi-1.csv'))).to eq(JSON.load(fixture_load('parsed-1.json'))) }
6 | it { expect(subject.parse(fixture_load('nvidia-smi-2.csv'))).to eq(JSON.load(fixture_load('parsed-2.json'))) }
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/spec/n_vidia_smi_xml_spec.rb:
--------------------------------------------------------------------------------
1 | RSpec.describe NVidiaSMI_XML do
2 | subject { described_class.new(binary_path: nil, name_prefix: 'rspec_') }
3 |
4 | context 'nvidia-smi-3.xml' do
5 | let(:result) do
6 | <<~EOS
7 | rspec_attached_gpus 2
8 | rspec_display_mode{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
9 | rspec_display_mode{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
10 | rspec_display_active{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
11 | rspec_display_active{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
12 | rspec_persistence_mode{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
13 | rspec_persistence_mode{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1
14 | rspec_accounting_mode{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
15 | rspec_accounting_mode{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
16 | rspec_accounting_mode_buffer_size{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 4000
17 | rspec_accounting_mode_buffer_size{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 4000
18 | rspec_minor_number{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
19 | rspec_minor_number{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1
20 | rspec_multigpu_board{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
21 | rspec_multigpu_board{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
22 | rspec_inforom_version_oem_object{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1.1
23 | rspec_inforom_version_oem_object{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1.1
24 | rspec_pci_pci_sub_system_id{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 37021458
25 | rspec_pci_pci_sub_system_id{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 37171458
26 | rspec_pci_pci_gpu_link_info_pcie_gen_max_link_gen{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 3
27 | rspec_pci_pci_gpu_link_info_pcie_gen_max_link_gen{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 3
28 | rspec_pci_pci_gpu_link_info_pcie_gen_current_link_gen{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 3
29 | rspec_pci_pci_gpu_link_info_pcie_gen_current_link_gen{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 3
30 | rspec_pci_pci_gpu_link_info_link_widths_max_link_width{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 16
31 | rspec_pci_pci_gpu_link_info_link_widths_max_link_width{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 16
32 | rspec_pci_pci_gpu_link_info_link_widths_current_link_width{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
33 | rspec_pci_pci_gpu_link_info_link_widths_current_link_width{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1
34 | rspec_pci_replay_counter{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 65535
35 | rspec_pci_replay_counter{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 552
36 | rspec_pci_replay_rollover_counter{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
37 | rspec_pci_replay_rollover_counter{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
38 | rspec_pci_tx_util_bytes_per_second{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 11264000
39 | rspec_pci_tx_util_bytes_per_second{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 11264000
40 | rspec_pci_rx_util_bytes_per_second{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 31744000
41 | rspec_pci_rx_util_bytes_per_second{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 31744000
42 | rspec_fan_speed_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0.53
43 | rspec_fan_speed_ratio{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0.58
44 | rspec_performance_state{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 2
45 | rspec_performance_state{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 2
46 | rspec_clocks_throttle_reasons_clocks_throttle_reason_gpu_idle{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
47 | rspec_clocks_throttle_reasons_clocks_throttle_reason_gpu_idle{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
48 | rspec_clocks_throttle_reasons_clocks_throttle_reason_applications_clocks_setting{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
49 | rspec_clocks_throttle_reasons_clocks_throttle_reason_applications_clocks_setting{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
50 | rspec_clocks_throttle_reasons_clocks_throttle_reason_sw_power_cap{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
51 | rspec_clocks_throttle_reasons_clocks_throttle_reason_sw_power_cap{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1
52 | rspec_clocks_throttle_reasons_clocks_throttle_reason_hw_slowdown{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
53 | rspec_clocks_throttle_reasons_clocks_throttle_reason_hw_slowdown{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
54 | rspec_clocks_throttle_reasons_clocks_throttle_reason_hw_thermal_slowdown{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
55 | rspec_clocks_throttle_reasons_clocks_throttle_reason_hw_thermal_slowdown{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
56 | rspec_clocks_throttle_reasons_clocks_throttle_reason_hw_power_brake_slowdown{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
57 | rspec_clocks_throttle_reasons_clocks_throttle_reason_hw_power_brake_slowdown{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
58 | rspec_clocks_throttle_reasons_clocks_throttle_reason_sync_boost{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
59 | rspec_clocks_throttle_reasons_clocks_throttle_reason_sync_boost{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
60 | rspec_clocks_throttle_reasons_clocks_throttle_reason_sw_thermal_slowdown{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
61 | rspec_clocks_throttle_reasons_clocks_throttle_reason_sw_thermal_slowdown{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
62 | rspec_clocks_throttle_reasons_clocks_throttle_reason_display_clocks_setting{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
63 | rspec_clocks_throttle_reasons_clocks_throttle_reason_display_clocks_setting{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
64 | rspec_fb_memory_usage_total_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 8510242816
65 | rspec_fb_memory_usage_total_bytes{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 8513388544
66 | rspec_fb_memory_usage_used_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 3040870400
67 | rspec_fb_memory_usage_used_bytes{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 3033530368
68 | rspec_fb_memory_usage_free_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 5469372416
69 | rspec_fb_memory_usage_free_bytes{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 5479858176
70 | rspec_bar1_memory_usage_total_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 268435456
71 | rspec_bar1_memory_usage_total_bytes{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 268435456
72 | rspec_bar1_memory_usage_used_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 5242880
73 | rspec_bar1_memory_usage_used_bytes{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 5242880
74 | rspec_bar1_memory_usage_free_bytes{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 263192576
75 | rspec_bar1_memory_usage_free_bytes{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 263192576
76 | rspec_compute_mode{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
77 | rspec_compute_mode{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
78 | rspec_utilization_gpu_util_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1.0
79 | rspec_utilization_gpu_util_ratio{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1.0
80 | rspec_utilization_memory_util_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1.0
81 | rspec_utilization_memory_util_ratio{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1.0
82 | rspec_utilization_encoder_util_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0.0
83 | rspec_utilization_encoder_util_ratio{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0.0
84 | rspec_utilization_decoder_util_ratio{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0.0
85 | rspec_utilization_decoder_util_ratio{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0.0
86 | rspec_encoder_stats_session_count{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
87 | rspec_encoder_stats_session_count{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
88 | rspec_encoder_stats_average_fps{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
89 | rspec_encoder_stats_average_fps{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
90 | rspec_encoder_stats_average_latency{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
91 | rspec_encoder_stats_average_latency{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
92 | rspec_fbc_stats_session_count{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
93 | rspec_fbc_stats_session_count{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
94 | rspec_fbc_stats_average_fps{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
95 | rspec_fbc_stats_average_fps{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
96 | rspec_fbc_stats_average_latency{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 0
97 | rspec_fbc_stats_average_latency{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 0
98 | rspec_temperature_gpu_temp_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 67.0
99 | rspec_temperature_gpu_temp_celsius{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 70.0
100 | rspec_temperature_gpu_temp_max_threshold_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 96.0
101 | rspec_temperature_gpu_temp_max_threshold_celsius{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 96.0
102 | rspec_temperature_gpu_temp_slow_threshold_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 93.0
103 | rspec_temperature_gpu_temp_slow_threshold_celsius{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 93.0
104 | rspec_temperature_gpu_target_temperature_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 83.0
105 | rspec_temperature_gpu_target_temperature_celsius{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 83.0
106 | rspec_supported_gpu_target_temp_gpu_target_temp_min_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 60.0
107 | rspec_supported_gpu_target_temp_gpu_target_temp_min_celsius{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 60.0
108 | rspec_supported_gpu_target_temp_gpu_target_temp_max_celsius{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 92.0
109 | rspec_supported_gpu_target_temp_gpu_target_temp_max_celsius{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 92.0
110 | rspec_power_readings_power_state{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 2
111 | rspec_power_readings_power_state{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 2
112 | rspec_power_readings_power_management{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1
113 | rspec_power_readings_power_management{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1
114 | rspec_power_readings_power_draw_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 211.86
115 | rspec_power_readings_power_draw_watts{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 211.06
116 | rspec_power_readings_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 216.0
117 | rspec_power_readings_power_limit_watts{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 216.0
118 | rspec_power_readings_default_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 200.0
119 | rspec_power_readings_default_power_limit_watts{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 200.0
120 | rspec_power_readings_enforced_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 216.0
121 | rspec_power_readings_enforced_power_limit_watts{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 216.0
122 | rspec_power_readings_min_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 100.0
123 | rspec_power_readings_min_power_limit_watts{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 100.0
124 | rspec_power_readings_max_power_limit_watts{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 216.0
125 | rspec_power_readings_max_power_limit_watts{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 216.0
126 | rspec_clocks_graphics_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1784000000.0
127 | rspec_clocks_graphics_clock_hz{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1657000000.0
128 | rspec_clocks_sm_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1784000000.0
129 | rspec_clocks_sm_clock_hz{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1657000000.0
130 | rspec_clocks_mem_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 5514000000.0
131 | rspec_clocks_mem_clock_hz{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 5514000000.0
132 | rspec_clocks_video_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1594000000.0
133 | rspec_clocks_video_clock_hz{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1480000000.0
134 | rspec_max_clocks_graphics_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1999000000.0
135 | rspec_max_clocks_graphics_clock_hz{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1936000000.0
136 | rspec_max_clocks_sm_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1999000000.0
137 | rspec_max_clocks_sm_clock_hz{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1936000000.0
138 | rspec_max_clocks_mem_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 5005000000.0
139 | rspec_max_clocks_mem_clock_hz{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 5005000000.0
140 | rspec_max_clocks_video_clock_hz{uuid="683c6e09-3969-31a5-b7ca-cc88252b7fce"} 1708000000.0
141 | rspec_max_clocks_video_clock_hz{uuid="90e3dab0-b59d-8bf6-d909-d4fab8d2f29b"} 1708000000.0
142 | EOS
143 | end
144 |
145 | it do
146 | hash = subject.parse(fixture_load('nvidia-smi-3.xml'))
147 | expect(subject.format_prometheus(hash)).to eq(result)
148 | end
149 | end
150 |
151 | context 'nvidia-smi-4.xml' do
152 | let(:result) do
153 | <<~EOS
154 | rspec_attached_gpus 1
155 | rspec_display_mode{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
156 | rspec_display_active{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
157 | rspec_persistence_mode{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
158 | rspec_accounting_mode{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
159 | rspec_accounting_mode_buffer_size{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 4000
160 | rspec_minor_number{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
161 | rspec_multigpu_board{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
162 | rspec_inforom_version_oem_object{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1.1
163 | rspec_pci_pci_gpu_link_info_pcie_gen_max_link_gen{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 3
164 | rspec_pci_pci_gpu_link_info_pcie_gen_current_link_gen{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 3
165 | rspec_pci_pci_gpu_link_info_link_widths_max_link_width{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 16
166 | rspec_pci_pci_gpu_link_info_link_widths_current_link_width{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 16
167 | rspec_pci_replay_counter{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
168 | rspec_pci_replay_rollover_counter{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
169 | rspec_pci_tx_util_bytes_per_second{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
170 | rspec_pci_rx_util_bytes_per_second{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
171 | rspec_fan_speed_ratio{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0.61
172 | rspec_performance_state{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
173 | rspec_clocks_throttle_reasons_clocks_throttle_reason_gpu_idle{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
174 | rspec_clocks_throttle_reasons_clocks_throttle_reason_applications_clocks_setting{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
175 | rspec_clocks_throttle_reasons_clocks_throttle_reason_sw_power_cap{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
176 | rspec_clocks_throttle_reasons_clocks_throttle_reason_hw_slowdown{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
177 | rspec_clocks_throttle_reasons_clocks_throttle_reason_hw_thermal_slowdown{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
178 | rspec_clocks_throttle_reasons_clocks_throttle_reason_hw_power_brake_slowdown{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
179 | rspec_clocks_throttle_reasons_clocks_throttle_reason_sync_boost{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
180 | rspec_clocks_throttle_reasons_clocks_throttle_reason_sw_thermal_slowdown{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
181 | rspec_clocks_throttle_reasons_clocks_throttle_reason_display_clocks_setting{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
182 | rspec_fb_memory_usage_total_bytes{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 5304745984
183 | rspec_fb_memory_usage_used_bytes{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 334495744
184 | rspec_fb_memory_usage_free_bytes{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 4970250240
185 | rspec_bar1_memory_usage_total_bytes{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 268435456
186 | rspec_bar1_memory_usage_used_bytes{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 2097152
187 | rspec_bar1_memory_usage_free_bytes{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 266338304
188 | rspec_compute_mode{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
189 | rspec_utilization_gpu_util_ratio{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0.0
190 | rspec_utilization_memory_util_ratio{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0.0
191 | rspec_utilization_encoder_util_ratio{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0.0
192 | rspec_utilization_decoder_util_ratio{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0.0
193 | rspec_encoder_stats_session_count{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
194 | rspec_encoder_stats_average_fps{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
195 | rspec_encoder_stats_average_latency{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
196 | rspec_fbc_stats_session_count{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
197 | rspec_fbc_stats_average_fps{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
198 | rspec_fbc_stats_average_latency{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
199 | rspec_temperature_gpu_temp_celsius{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 62.0
200 | rspec_temperature_gpu_temp_max_threshold_celsius{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 104.0
201 | rspec_temperature_gpu_temp_slow_threshold_celsius{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 101.0
202 | rspec_power_readings_power_state{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 0
203 | rspec_power_readings_power_management{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1
204 | rspec_power_readings_power_draw_watts{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 20.32
205 | rspec_power_readings_power_limit_watts{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 75.0
206 | rspec_power_readings_default_power_limit_watts{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 75.0
207 | rspec_power_readings_enforced_power_limit_watts{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 75.0
208 | rspec_power_readings_min_power_limit_watts{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 75.0
209 | rspec_power_readings_max_power_limit_watts{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 75.0
210 | rspec_clocks_graphics_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1215000000.0
211 | rspec_clocks_sm_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1215000000.0
212 | rspec_clocks_mem_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 3499000000.0
213 | rspec_clocks_video_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1101000000.0
214 | rspec_applications_clocks_graphics_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1075000000.0
215 | rspec_applications_clocks_mem_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 3504000000.0
216 | rspec_default_applications_clocks_graphics_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1075000000.0
217 | rspec_default_applications_clocks_mem_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 3504000000.0
218 | rspec_max_clocks_graphics_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1721000000.0
219 | rspec_max_clocks_sm_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1721000000.0
220 | rspec_max_clocks_mem_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 3504000000.0
221 | rspec_max_clocks_video_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1556000000.0
222 | rspec_max_customer_boost_clocks_graphics_clock_hz{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 1721000000.0
223 | rspec_processes_process_info_pid{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 7134
224 | rspec_processes_process_info_used_memory_bytes{uuid="1ffe36ef-ac55-60ad-f9cf-623871e7736d"} 324009984
225 | EOS
226 | end
227 |
228 | it do
229 | hash = subject.parse(fixture_load('nvidia-smi-4.xml'))
230 | expect(subject.format_prometheus(hash)).to eq(result)
231 | end
232 | end
233 | end
234 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require 'helpers/fixture'
2 | require_relative '../app/n_vidia_smi'
3 | require_relative '../app/n_vidia_smi_xml'
4 | require 'json'
5 | require 'pry'
6 |
7 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
8 | RSpec.configure do |config|
9 | include Fixture
10 |
11 | config.expect_with :rspec do |expectations|
12 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true
13 | end
14 |
15 | config.mock_with :rspec do |mocks|
16 | mocks.verify_partial_doubles = true
17 | end
18 |
19 | config.shared_context_metadata_behavior = :apply_to_host_groups
20 |
21 | # The settings below are suggested to provide a good initial experience
22 | # with RSpec, but feel free to customize to your heart's content.
23 | =begin
24 | # This allows you to limit a spec run to individual examples or groups
25 | # you care about by tagging them with `:focus` metadata. When nothing
26 | # is tagged with `:focus`, all examples get run. RSpec also provides
27 | # aliases for `it`, `describe`, and `context` that include `:focus`
28 | # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
29 | config.filter_run_when_matching :focus
30 |
31 | # Allows RSpec to persist some state between runs in order to support
32 | # the `--only-failures` and `--next-failure` CLI options. We recommend
33 | # you configure your source control system to ignore this file.
34 | config.example_status_persistence_file_path = "spec/examples.txt"
35 |
36 | # Limits the available syntax to the non-monkey patched syntax that is
37 | # recommended. For more details, see:
38 | # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
39 | # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
40 | # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
41 | config.disable_monkey_patching!
42 |
43 | # This setting enables warnings. It's recommended, but in some cases may
44 | # be too noisy due to issues in dependencies.
45 | config.warnings = true
46 |
47 | # Many RSpec users commonly either run the entire suite or an individual
48 | # file, and it's useful to allow more verbose output when running an
49 | # individual spec file.
50 | if config.files_to_run.one?
51 | # Use the documentation formatter for detailed output,
52 | # unless a formatter has already been configured
53 | # (e.g. via a command-line flag).
54 | config.default_formatter = "doc"
55 | end
56 |
57 | # Print the 10 slowest examples and example groups at the
58 | # end of the spec run, to help surface which specs are running
59 | # particularly slow.
60 | config.profile_examples = 10
61 |
62 | # Run specs in random order to surface order dependencies. If you find an
63 | # order dependency and want to debug it, you can fix the order by providing
64 | # the seed, which is printed after each run.
65 | # --seed 1234
66 | config.order = :random
67 |
68 | # Seed global randomization in this process using the `--seed` CLI option.
69 | # Setting this allows you to use `--seed` to deterministically reproduce
70 | # test failures related to randomization by passing the same `--seed` value
71 | # as the one that triggered the failure.
72 | Kernel.srand config.seed
73 | =end
74 | end
75 |
--------------------------------------------------------------------------------