Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / github.com / prometheus / client_golang / prometheus / process_collector.go
1 // Copyright 2015 The Prometheus Authors
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package prometheus
15
16 import (
17         "errors"
18         "os"
19
20         "github.com/prometheus/procfs"
21 )
22
23 type processCollector struct {
24         collectFn       func(chan<- Metric)
25         pidFn           func() (int, error)
26         reportErrors    bool
27         cpuTotal        *Desc
28         openFDs, maxFDs *Desc
29         vsize, maxVsize *Desc
30         rss             *Desc
31         startTime       *Desc
32 }
33
34 // ProcessCollectorOpts defines the behavior of a process metrics collector
35 // created with NewProcessCollector.
36 type ProcessCollectorOpts struct {
37         // PidFn returns the PID of the process the collector collects metrics
38         // for. It is called upon each collection. By default, the PID of the
39         // current process is used, as determined on construction time by
40         // calling os.Getpid().
41         PidFn func() (int, error)
42         // If non-empty, each of the collected metrics is prefixed by the
43         // provided string and an underscore ("_").
44         Namespace string
45         // If true, any error encountered during collection is reported as an
46         // invalid metric (see NewInvalidMetric). Otherwise, errors are ignored
47         // and the collected metrics will be incomplete. (Possibly, no metrics
48         // will be collected at all.) While that's usually not desired, it is
49         // appropriate for the common "mix-in" of process metrics, where process
50         // metrics are nice to have, but failing to collect them should not
51         // disrupt the collection of the remaining metrics.
52         ReportErrors bool
53 }
54
55 // NewProcessCollector returns a collector which exports the current state of
56 // process metrics including CPU, memory and file descriptor usage as well as
57 // the process start time. The detailed behavior is defined by the provided
58 // ProcessCollectorOpts. The zero value of ProcessCollectorOpts creates a
59 // collector for the current process with an empty namespace string and no error
60 // reporting.
61 //
62 // Currently, the collector depends on a Linux-style proc filesystem and
63 // therefore only exports metrics for Linux.
64 //
65 // Note: An older version of this function had the following signature:
66 //
67 //     NewProcessCollector(pid int, namespace string) Collector
68 //
69 // Most commonly, it was called as
70 //
71 //     NewProcessCollector(os.Getpid(), "")
72 //
73 // The following call of the current version is equivalent to the above:
74 //
75 //     NewProcessCollector(ProcessCollectorOpts{})
76 func NewProcessCollector(opts ProcessCollectorOpts) Collector {
77         ns := ""
78         if len(opts.Namespace) > 0 {
79                 ns = opts.Namespace + "_"
80         }
81
82         c := &processCollector{
83                 reportErrors: opts.ReportErrors,
84                 cpuTotal: NewDesc(
85                         ns+"process_cpu_seconds_total",
86                         "Total user and system CPU time spent in seconds.",
87                         nil, nil,
88                 ),
89                 openFDs: NewDesc(
90                         ns+"process_open_fds",
91                         "Number of open file descriptors.",
92                         nil, nil,
93                 ),
94                 maxFDs: NewDesc(
95                         ns+"process_max_fds",
96                         "Maximum number of open file descriptors.",
97                         nil, nil,
98                 ),
99                 vsize: NewDesc(
100                         ns+"process_virtual_memory_bytes",
101                         "Virtual memory size in bytes.",
102                         nil, nil,
103                 ),
104                 maxVsize: NewDesc(
105                         ns+"process_virtual_memory_max_bytes",
106                         "Maximum amount of virtual memory available in bytes.",
107                         nil, nil,
108                 ),
109                 rss: NewDesc(
110                         ns+"process_resident_memory_bytes",
111                         "Resident memory size in bytes.",
112                         nil, nil,
113                 ),
114                 startTime: NewDesc(
115                         ns+"process_start_time_seconds",
116                         "Start time of the process since unix epoch in seconds.",
117                         nil, nil,
118                 ),
119         }
120
121         if opts.PidFn == nil {
122                 pid := os.Getpid()
123                 c.pidFn = func() (int, error) { return pid, nil }
124         } else {
125                 c.pidFn = opts.PidFn
126         }
127
128         // Set up process metric collection if supported by the runtime.
129         if _, err := procfs.NewStat(); err == nil {
130                 c.collectFn = c.processCollect
131         } else {
132                 c.collectFn = func(ch chan<- Metric) {
133                         c.reportError(ch, nil, errors.New("process metrics not supported on this platform"))
134                 }
135         }
136
137         return c
138 }
139
140 // Describe returns all descriptions of the collector.
141 func (c *processCollector) Describe(ch chan<- *Desc) {
142         ch <- c.cpuTotal
143         ch <- c.openFDs
144         ch <- c.maxFDs
145         ch <- c.vsize
146         ch <- c.maxVsize
147         ch <- c.rss
148         ch <- c.startTime
149 }
150
151 // Collect returns the current state of all metrics of the collector.
152 func (c *processCollector) Collect(ch chan<- Metric) {
153         c.collectFn(ch)
154 }
155
156 func (c *processCollector) processCollect(ch chan<- Metric) {
157         pid, err := c.pidFn()
158         if err != nil {
159                 c.reportError(ch, nil, err)
160                 return
161         }
162
163         p, err := procfs.NewProc(pid)
164         if err != nil {
165                 c.reportError(ch, nil, err)
166                 return
167         }
168
169         if stat, err := p.NewStat(); err == nil {
170                 ch <- MustNewConstMetric(c.cpuTotal, CounterValue, stat.CPUTime())
171                 ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(stat.VirtualMemory()))
172                 ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory()))
173                 if startTime, err := stat.StartTime(); err == nil {
174                         ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime)
175                 } else {
176                         c.reportError(ch, c.startTime, err)
177                 }
178         } else {
179                 c.reportError(ch, nil, err)
180         }
181
182         if fds, err := p.FileDescriptorsLen(); err == nil {
183                 ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds))
184         } else {
185                 c.reportError(ch, c.openFDs, err)
186         }
187
188         if limits, err := p.NewLimits(); err == nil {
189                 ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles))
190                 ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(limits.AddressSpace))
191         } else {
192                 c.reportError(ch, nil, err)
193         }
194 }
195
196 func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) {
197         if !c.reportErrors {
198                 return
199         }
200         if desc == nil {
201                 desc = NewInvalidDesc(err)
202         }
203         ch <- NewInvalidMetric(desc, err)
204 }