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
6 // http://www.apache.org/licenses/LICENSE-2.0
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.
20 "github.com/prometheus/procfs"
23 type processCollector struct {
24 collectFn func(chan<- Metric)
25 pidFn func() (int, error)
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 ("_").
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.
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
62 // Currently, the collector depends on a Linux-style proc filesystem and
63 // therefore only exports metrics for Linux.
65 // Note: An older version of this function had the following signature:
67 // NewProcessCollector(pid int, namespace string) Collector
69 // Most commonly, it was called as
71 // NewProcessCollector(os.Getpid(), "")
73 // The following call of the current version is equivalent to the above:
75 // NewProcessCollector(ProcessCollectorOpts{})
76 func NewProcessCollector(opts ProcessCollectorOpts) Collector {
78 if len(opts.Namespace) > 0 {
79 ns = opts.Namespace + "_"
82 c := &processCollector{
83 reportErrors: opts.ReportErrors,
85 ns+"process_cpu_seconds_total",
86 "Total user and system CPU time spent in seconds.",
90 ns+"process_open_fds",
91 "Number of open file descriptors.",
96 "Maximum number of open file descriptors.",
100 ns+"process_virtual_memory_bytes",
101 "Virtual memory size in bytes.",
105 ns+"process_virtual_memory_max_bytes",
106 "Maximum amount of virtual memory available in bytes.",
110 ns+"process_resident_memory_bytes",
111 "Resident memory size in bytes.",
115 ns+"process_start_time_seconds",
116 "Start time of the process since unix epoch in seconds.",
121 if opts.PidFn == nil {
123 c.pidFn = func() (int, error) { return pid, nil }
128 // Set up process metric collection if supported by the runtime.
129 if _, err := procfs.NewStat(); err == nil {
130 c.collectFn = c.processCollect
132 c.collectFn = func(ch chan<- Metric) {
133 c.reportError(ch, nil, errors.New("process metrics not supported on this platform"))
140 // Describe returns all descriptions of the collector.
141 func (c *processCollector) Describe(ch chan<- *Desc) {
151 // Collect returns the current state of all metrics of the collector.
152 func (c *processCollector) Collect(ch chan<- Metric) {
156 func (c *processCollector) processCollect(ch chan<- Metric) {
157 pid, err := c.pidFn()
159 c.reportError(ch, nil, err)
163 p, err := procfs.NewProc(pid)
165 c.reportError(ch, nil, err)
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)
176 c.reportError(ch, c.startTime, err)
179 c.reportError(ch, nil, err)
182 if fds, err := p.FileDescriptorsLen(); err == nil {
183 ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds))
185 c.reportError(ch, c.openFDs, err)
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))
192 c.reportError(ch, nil, err)
196 func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) {
201 desc = NewInvalidDesc(err)
203 ch <- NewInvalidMetric(desc, err)