blob: 5bfe0ff5bbc9e955e2e3aacc5edd7dae3472d595 [file] [log] [blame]
khenaidoo59ce9dd2019-11-11 13:05:32 -05001// 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
14package prometheus
15
16import (
17 "errors"
khenaidoo26721882021-08-11 17:42:52 -040018 "fmt"
19 "io/ioutil"
khenaidoo59ce9dd2019-11-11 13:05:32 -050020 "os"
khenaidoo26721882021-08-11 17:42:52 -040021 "strconv"
22 "strings"
khenaidoo59ce9dd2019-11-11 13:05:32 -050023)
24
25type processCollector struct {
26 collectFn func(chan<- Metric)
27 pidFn func() (int, error)
28 reportErrors bool
29 cpuTotal *Desc
30 openFDs, maxFDs *Desc
31 vsize, maxVsize *Desc
32 rss *Desc
33 startTime *Desc
34}
35
36// ProcessCollectorOpts defines the behavior of a process metrics collector
37// created with NewProcessCollector.
38type ProcessCollectorOpts struct {
39 // PidFn returns the PID of the process the collector collects metrics
40 // for. It is called upon each collection. By default, the PID of the
41 // current process is used, as determined on construction time by
42 // calling os.Getpid().
43 PidFn func() (int, error)
44 // If non-empty, each of the collected metrics is prefixed by the
45 // provided string and an underscore ("_").
46 Namespace string
47 // If true, any error encountered during collection is reported as an
48 // invalid metric (see NewInvalidMetric). Otherwise, errors are ignored
49 // and the collected metrics will be incomplete. (Possibly, no metrics
50 // will be collected at all.) While that's usually not desired, it is
51 // appropriate for the common "mix-in" of process metrics, where process
52 // metrics are nice to have, but failing to collect them should not
53 // disrupt the collection of the remaining metrics.
54 ReportErrors bool
55}
56
khenaidoo26721882021-08-11 17:42:52 -040057// NewProcessCollector is the obsolete version of collectors.NewProcessCollector.
58// See there for documentation.
khenaidoo59ce9dd2019-11-11 13:05:32 -050059//
khenaidoo26721882021-08-11 17:42:52 -040060// Deprecated: Use collectors.NewProcessCollector instead.
khenaidoo59ce9dd2019-11-11 13:05:32 -050061func NewProcessCollector(opts ProcessCollectorOpts) Collector {
62 ns := ""
63 if len(opts.Namespace) > 0 {
64 ns = opts.Namespace + "_"
65 }
66
67 c := &processCollector{
68 reportErrors: opts.ReportErrors,
69 cpuTotal: NewDesc(
70 ns+"process_cpu_seconds_total",
71 "Total user and system CPU time spent in seconds.",
72 nil, nil,
73 ),
74 openFDs: NewDesc(
75 ns+"process_open_fds",
76 "Number of open file descriptors.",
77 nil, nil,
78 ),
79 maxFDs: NewDesc(
80 ns+"process_max_fds",
81 "Maximum number of open file descriptors.",
82 nil, nil,
83 ),
84 vsize: NewDesc(
85 ns+"process_virtual_memory_bytes",
86 "Virtual memory size in bytes.",
87 nil, nil,
88 ),
89 maxVsize: NewDesc(
90 ns+"process_virtual_memory_max_bytes",
91 "Maximum amount of virtual memory available in bytes.",
92 nil, nil,
93 ),
94 rss: NewDesc(
95 ns+"process_resident_memory_bytes",
96 "Resident memory size in bytes.",
97 nil, nil,
98 ),
99 startTime: NewDesc(
100 ns+"process_start_time_seconds",
101 "Start time of the process since unix epoch in seconds.",
102 nil, nil,
103 ),
104 }
105
106 if opts.PidFn == nil {
107 pid := os.Getpid()
108 c.pidFn = func() (int, error) { return pid, nil }
109 } else {
110 c.pidFn = opts.PidFn
111 }
112
113 // Set up process metric collection if supported by the runtime.
114 if canCollectProcess() {
115 c.collectFn = c.processCollect
116 } else {
117 c.collectFn = func(ch chan<- Metric) {
118 c.reportError(ch, nil, errors.New("process metrics not supported on this platform"))
119 }
120 }
121
122 return c
123}
124
125// Describe returns all descriptions of the collector.
126func (c *processCollector) Describe(ch chan<- *Desc) {
127 ch <- c.cpuTotal
128 ch <- c.openFDs
129 ch <- c.maxFDs
130 ch <- c.vsize
131 ch <- c.maxVsize
132 ch <- c.rss
133 ch <- c.startTime
134}
135
136// Collect returns the current state of all metrics of the collector.
137func (c *processCollector) Collect(ch chan<- Metric) {
138 c.collectFn(ch)
139}
140
141func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) {
142 if !c.reportErrors {
143 return
144 }
145 if desc == nil {
146 desc = NewInvalidDesc(err)
147 }
148 ch <- NewInvalidMetric(desc, err)
149}
khenaidoo26721882021-08-11 17:42:52 -0400150
151// NewPidFileFn returns a function that retrieves a pid from the specified file.
152// It is meant to be used for the PidFn field in ProcessCollectorOpts.
153func NewPidFileFn(pidFilePath string) func() (int, error) {
154 return func() (int, error) {
155 content, err := ioutil.ReadFile(pidFilePath)
156 if err != nil {
157 return 0, fmt.Errorf("can't read pid file %q: %+v", pidFilePath, err)
158 }
159 pid, err := strconv.Atoi(strings.TrimSpace(string(content)))
160 if err != nil {
161 return 0, fmt.Errorf("can't parse pid file %q: %+v", pidFilePath, err)
162 }
163
164 return pid, nil
165 }
166}