master
go 120 lines 2.52 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package nvidia_smi
4
5 import (
6 "context"
7 _ "embed"
8 "errors"
9 "runtime"
10 "time"
11
12 "github.com/netdata/netdata/go/plugins/pkg/confopt"
13 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
14 )
15
16 //go:embed "config_schema.json"
17 var configSchema string
18
19 func init() {
20 collectorapi.Register("nvidia_smi", collectorapi.Creator{
21 JobConfigSchema: configSchema,
22 Defaults: collectorapi.Defaults{
23 UpdateEvery: 10,
24 },
25 Create: func() collectorapi.CollectorV1 { return New() },
26 Config: func() any { return &Config{} },
27 })
28 }
29
30 func New() *Collector {
31 return &Collector{
32 Config: Config{
33 Timeout: confopt.Duration(time.Second * 10),
34 // Disable loop mode on Windows due to go.d.plugin's non-graceful exit
35 // which can leave `nvidia_smi` processes running indefinitely.
36 LoopMode: !(runtime.GOOS == "windows"),
37 },
38 binName: "nvidia-smi",
39 charts: &collectorapi.Charts{},
40 gpus: make(map[string]bool),
41 migs: make(map[string]bool),
42 }
43
44 }
45
46 type Config struct {
47 UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
48 AutoDetectionRetry int `yaml:"autodetection_retry,omitempty" json:"autodetection_retry"`
49 Timeout confopt.Duration `yaml:"timeout,omitempty" json:"timeout"`
50 BinaryPath string `yaml:"binary_path" json:"binary_path"`
51 LoopMode bool `yaml:"loop_mode,omitempty" json:"loop_mode"`
52 }
53
54 type Collector struct {
55 collectorapi.Base
56 Config `yaml:",inline" json:""`
57
58 charts *collectorapi.Charts
59
60 exec nvidiaSmiBinary
61 binName string
62
63 gpus map[string]bool
64 migs map[string]bool
65 }
66
67 func (c *Collector) Configuration() any {
68 return c.Config
69 }
70
71 func (c *Collector) Init(context.Context) error {
72 if c.exec == nil {
73 if runtime.GOOS == "windows" && c.LoopMode {
74 c.LoopMode = false
75 }
76 smi, err := c.initNvidiaSmiExec()
77 if err != nil {
78 return err
79 }
80 c.exec = smi
81 }
82
83 return nil
84 }
85
86 func (c *Collector) Check(context.Context) error {
87 mx, err := c.collect()
88 if err != nil {
89 return err
90 }
91 if len(mx) == 0 {
92 return errors.New("no metrics collected")
93 }
94 return nil
95 }
96
97 func (c *Collector) Charts() *collectorapi.Charts {
98 return c.charts
99 }
100
101 func (c *Collector) Collect(context.Context) map[string]int64 {
102 mx, err := c.collect()
103 if err != nil {
104 c.Error(err)
105 }
106
107 if len(mx) == 0 {
108 return nil
109 }
110 return mx
111 }
112
113 func (c *Collector) Cleanup(context.Context) {
114 if c.exec != nil {
115 if err := c.exec.stop(); err != nil {
116 c.Errorf("cleanup: %v", err)
117 }
118 c.exec = nil
119 }
120 }